将班级成员存储为原始指针的替代方案

发布于 2025-01-25 07:14:48 字数 1124 浏览 2 评论 0原文

在下面显示的代码示例中 - 在container类中,拥有(并且负责销毁)两个对象c,d,是子类抽象类b的。 容器对象可以创建新的ObjectDisplay在其构造函数中采用一种B。我可以将抽象类型B作为指针将其传递到objectDisplay中,并将其存储为原始指针。但这并不理想地存储&使用原始指针,并始终检查是否是空指针。如果B不是抽象类,我可以将其传递给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;
};

In the code example shown below - in Container class, it owns (and is responsible fore destroying) two objects c, d, which are subclasses of an abstract class B. Container object can create new ObjectDisplay that takes a kind of B in its constructor. I can pass the abstract type B as a pointer into ObjectDisplay and store it as a RAW pointer. But it's not ideal to store & use a raw pointer and always check if it's a null pointer. 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 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;
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

野心澎湃 2025-02-01 07:14:48

如果B不是抽象类,我可以将其作为参考

将其传递给ObjectDisplay

,如果B是抽象类,则仍然可以通过参考将其传递。 b&amp;对象可以绑定到b的子类的实例。它的行为与指针几乎相同。

cppref

也就是说,如果使用指针或对基类的引用来处理派生的类,则调用覆盖虚拟函数的调用将调用派生类中定义的行为。

b&amp;中声明objectdisplay中的成员,然后通过参考来构造它。

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

请参阅在线
由于您正在传递临时objectDisplay直接在push_back中构造的对象,因此我建议您使用emplace_back

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

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

No, if B is an abstract class, you can still pass it by reference. B& object can be bound to an instance of B's subclass. It behaves almost the same as pointers.

As quoted in 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.

Declare a member of B& in ObjectDisplay and construct it through a reference.

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));    
    }
};

See online demo

Aside:
Since you are passing a temporary ObjectDisplay object directly constructed in push_back, I recommend you to use emplace_back.

    void addDisplay()
    {
        displays.emplace_back (c);
        displays.emplace_back (d);
    }
我很坚强 2025-02-01 07:14:48

如果b不是抽象类,我可以将其传递给objectDisplay作为参考(即object> objectdisplay(b&amp; b))。但是由于我无法更改b,我想知道存储b* object作为objectdisplay

仅仅因为b是一个抽象类,并不意味着您必须将其传递给它并将其存储为 pointer 。您也可以将其传递给它,并将其存储为参考。多态性与指针和参考作用。并且使用参考确实可以解决您的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;
};

演示

在线 因为cdobjectdisplay显示中的对象中,您都会很好,无论您使用指针还是参考。

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?

Just because B is an abstract class does not mean you are required to pass it around and store it as a pointer. You CAN pass it around and store it as a reference as well. Polymorphism works with pointers AND references. And using a reference would indeed solve your nullptr issue, eg:

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

As long as c and d outlive the ObjectDisplay objects in displays, you will be just fine, whether you use pointers or references.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文