首页 > 解决方案 > C++:避免​​构造函数中成员的 nullptr 初始化

问题描述

像这样的一类

class A{
    public:

    const B& instanceOfB ;

    A(const B& someInstanceOfB):
        instanceOfB(someInstanceOfB)
    {
    };

    // some methods depending on instanceOfB here

};

应该扩展以提供一些不依赖于 的instanceOfB方法,并且这些方法必须可以在没有任何的情况下访问instanceOfB(即,根本不B存在 的实例)。

因此,直接的扩展可能看起来像

class A{

    public:

    B* const instanceOfB ;

    A():
    instanceOfB(nullptr)
    {
    }

    // some methods not depending on instanceOfB here

    void assignInstanceOfB(B* const someInstanceOfB){
        instanceOfB = someInstanceOfB;};

    // some methods depending on instanceOfB here

};

但是,在我看来,这有几个缺点:

所以我对这个设计并不满意。看起来更复杂的版本会是什么样子?谢谢!

编辑:由于评论,我添加了以下附加要求: - 无法拆分类 - 必须存储对 B 的引用,不能仅将其交给相应的方法。

总而言之,使用指针(包括智能指针)似乎是推荐的或至少是常用的方法。

标签: c++

解决方案


为了解决您在使用对象之前必须调用初始化函数的第一个问题,您可以实现两个构造函数。一个会接收一个指向的指针,B另一个默认将指针置空。

class A{
    public:

    B* const instanceOfB ;

    A(B* const b) : instanceOfB(b) { }

    A() : A(nullptr) { }
};

关于您的第三个问题,使用非拥有指针是存储对可能存在或不存在的对象的引用的常用方法。如果您一心不使用指针,您可以使用std::optional如下方式:

class A
{
public:
    std::optional<std::reference_wrapper<B>> instanceOfB;

    A(B * const b = nullptr) : instanceOfB(std::nullopt)
    {
         if (b != nullptr)
         {
             instanceOfB = std::make_optional(std::ref(*b));
         }
    }

    void doSomething()
    {
        if (!instanceOfB)
        {
            return;
        }

        instanceOfB->get().something();
    }
};

您需要使用std::reference_wrapper,因为std::optional明确不支持直接存储引用。您仍然需要在使用它之前检查可选项是否包含任何内容,因此您最终仍然需要与检查空指针非常相似的代码。访问内部引用的语法更糟糕,如doSomething(). 最后,这似乎没有任何好处,我不会推荐它。


推荐阅读