将 class 成员存储为原始指针的替代方法

Alternatives for storing a class member as a raw pointer

在下面显示的代码示例中 - 在 Container class 中,它 拥有 (并负责销毁)两个对象 c, d ,它们是摘要 class B 的子classes。 Container 对象可以创建新的 ObjectDisplay 在其构造函数中采用一种 B 。我可以将抽象类型 B 作为指针传递给 ObjectDisplay 并将其存储为 RAW 指针 。但是存储和使用原始指针并始终检查它是否为空指针并不理想。如果 B 不是抽象的 class,我可以将其作为参考传递给 ObjectDisplay(即 ObjectDisplay (B& b))。但由于我无法更改 B,我想知道将 B* 对象作为原始指针存储在 ObjectDisplay 中的替代方案是什么?

// B is abstract
class B
{
public:
    virtual int getDefault() = 0;
};

class C : public B
{
public:
    int getDefault() override { return 1; }
};

class D : public B
{
public:
    int getDefault() override { return 5; }
};

class ObjectDisplay
{
public:
ObjectDisplay (B* b) : object (b) {}

void someFunction()
{
    const auto result = b->getDefault();
    // do something
}

private:
B* object;
};

class Container
{
public:
    void addDisplay()
    {
    displays.push_back (ObjectDisplay (&c));
    displays.push_back (ObjectDisplay (&d));    
    }
private:
    C c;
    D d;
    std::vector<ObjectDisplay> displays;
};

If B wasn't an abstract class, I could pass it in ObjectDisplay as a reference (ie. ObjectDisplay (B& b)). But since I can't change B, I wonder what's the aternative of storing B* object as a raw pointer in ObjectDisplay?

仅仅因为 B 是一个抽象 class 并不意味着您需要传递它并将其存储为 指针 。您可以传递它并将其存储为 reference。多态性适用于指针和引用。使用参考确实可以解决您的 nullptr 问题,例如:

class ObjectDisplay
{
public:
    ObjectDisplay (B& b) : object (b) {}

    void someFunction()
    {
        const auto result = object.getDefault();
        // do something
    }

private:
    B& object;
};

class Container
{
public:
    void addDisplay()
    {
        displays.push_back (ObjectDisplay (c));
        displays.push_back (ObjectDisplay (d));    
    }

private:
    C c;
    D d;
    std::vector<ObjectDisplay> displays;
};

Online Demo

只要 cd 的寿命超过 displays 中的 ObjectDisplay 个对象,无论您使用指针还是引用,都可以。

If B wasn't an abstract class, I could pass it in ObjectDisplay as a reference

不,如果 B 是一个抽象 class,您仍然可以通过引用传递它。 B& object 可以绑定到 B 的子 class 的实例。它的行为几乎与指针相同。

引自cppref

That is to say, if a derived class is handled using pointer or reference to the base class, a call to an overridden virtual function would invoke the behavior defined in the derived class.

ObjectDisplay中声明一个B&的成员,并通过引用构造它。

class ObjectDisplay
{
public:
    ObjectDisplay (B& b) : object (b) {}
private:
    B& object;

};

class Container
{
public:
    void addDisplay()
    {
        displays.push_back (ObjectDisplay (c));
        displays.push_back (ObjectDisplay (d));    
    }
};

在线查看demo

旁白: 由于您传递的是直接在 push_back 中构造的临时 ObjectDisplay 对象,我建议您使用 emplace_back.

    void addDisplay()
    {
        displays.emplace_back (c);
        displays.emplace_back (d);
    }