C++将抽象类的派生对象添加到另一个没有悬挂指针的类中?

标签 c++ containers abstract-class dangling-pointer

我有一个简单的容器类,它指向一个抽象类,我有函数来获取/设置容器类中的指针。更具体地说,该类如下所示:

class Container
{
    Abstract* thing;
public:
    void set(Abstract &obj)
    {
        thing = &obj; //danger of dangling pointer
    }

    Abstract* get()
    {
        return thing;
    }
};

Abstract 是一个抽象类。正如已经看到的那样,存在悬空指针的危险。我知道我可以复制对象(新)然后指向它。但是我不能创建抽象类的实例。有什么解决方案?


以下只是更多信息:

类定义

class Abstract
{
public:
    virtual void something() = 0;
};

class Base : public Abstract
{
    int a;
public:
    Base() {}
    Base(int a) : a(a){}
    virtual void something()
    {
        cout << "Base" << endl;
    }
};

class Derived : public Base
{
    int b;
public:
    Derived() {}
    Derived(int a, int b) : Base(a), b(b){}
    virtual void something()
    {
        cout << "Derived" << endl;
    }
};

简单测试

void setBase(Container &toSet)
{
    Base base(15);
    toSet.set(base);
}

void setDerived(Container &toSet)
{
    Derived derived(10, 30);
    toSet.set(derived);
}

int main()
{
    Container co;

    Base base(15);
    Derived derived(10, 30);

    Base *basePtr;
    Derived *derivedPtr;

    //This is fine
    co.set(base);
    basePtr = static_cast<Base *>(co.get());
    basePtr->something();

    //This is fine
    co.set(derived);
    derivedPtr = static_cast<Derived *>(co.get());
    derivedPtr->something();

    //Reset
    basePtr = nullptr;
    derivedPtr = nullptr;

    //Dangling pointer!
    setBase(co);
    basePtr = static_cast<Base *>(co.get());
    basePtr->something();

    //Dangling pointer!
    setDerived(co);
    derivedPtr = static_cast<Derived *>(co.get());
    derivedPtr->something();

    return 0;
}

最佳答案

您需要做的是具体定义您的内存所有权。

Container::set 通过引用接受 Abstract 的实例,这通常并不意味着所有权转移:

 void set(Abstract &obj){...} // Caller retains ownership of obj, but now we have a weak reference to it

那么删除的责任就不是你了。

Container::get 返回一个暗示所有权的指针,表明调用set 的人不应使传递的对象无效。

Abstract* get(){...}

正如您所说,这可能会有问题。

你有几个选择

  • 使用适当的文档 (Code by contract) 在 Container 中编码这些内存所有权语义
  • 使用像std::shared_ptr这样的智能指针

在前一种情况下,它是否有效取决于用户阅读和理解您的 API,然后很好地使用它。在后一种情况下,指针对象拥有自己,并将在最后一个实例超出范围时删除分配的内存。

 void set(std::shared_ptr<Abstract> obj){...} 
// now Container participates in the lifetime of obj, 
// and it's harder to nullify the underlying object 
// (you'd have to be intentionally misbehaving)

关于C++将抽象类的派生对象添加到另一个没有悬挂指针的类中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38578093/

相关文章:

lazy-loading - Vaadin-惰性查询容器

c++ - 抽象类的大小是多少?为什么我们不能创建抽象类的对象?

java - 需要弄清楚类抽象

c# - 在以下情况下正确使用抽象类或接口(interface)

c++ - 通过网络发送 CTRL-C

c++ - 使用 pthread 唤醒多线程的最佳方法

c++ - 使用一元调整大小减小非默认可构造元素的容器大小

c++ - 遍历链表

远程对象的 C++ 调用方法(类似于 RPC)

memory - 你能在 Kubernetes 上的 .NET Core 中触发 OOM 异常的自动内存转储吗?