C++ boost::scoped_ptr 的析构函数问题

发布于 2024-09-05 10:29:21 字数 951 浏览 7 评论 0原文

我对以下代码有疑问:

#include <iostream>
#include <boost/scoped_ptr.hpp>

class Interface
{
};

class A : public Interface
{
    public:
        A() { std::cout << "A()" << std::endl; }
        virtual ~A() { std::cout << "~A()" << std::endl; }
};


Interface* get_a()
{
    A* a = new A;
    return a;
}

int main()
{
    {
        std::cout << "1" << std::endl;
        boost::scoped_ptr<Interface> x(get_a());
        std::cout << "2" << std::endl;
    }
    std::cout << "3" << std::endl;
}

它创建以下输出:

1
A()
2
3

如您所见,它不会调用 A 的析构函数。 我认为调用 A 的析构函数的唯一方法是为 Interface 类添加一个析构函数,如下所示:

virtual ~Interface() { }

但我真的想避免在 Interface 类中使用任何实现,并且 virtual ~Interface() = 0; 不起作用(产生一些链接器错误,抱怨 ~Interface() 的实现不存在。

所以我的问题是:我必须更改什么才能使析构函数成为调用,但(如果可能)将接口保留为接口(仅抽象方法)。

I have a question about the following code:

#include <iostream>
#include <boost/scoped_ptr.hpp>

class Interface
{
};

class A : public Interface
{
    public:
        A() { std::cout << "A()" << std::endl; }
        virtual ~A() { std::cout << "~A()" << std::endl; }
};


Interface* get_a()
{
    A* a = new A;
    return a;
}

int main()
{
    {
        std::cout << "1" << std::endl;
        boost::scoped_ptr<Interface> x(get_a());
        std::cout << "2" << std::endl;
    }
    std::cout << "3" << std::endl;
}

It creates the following output:

1
A()
2
3

As you can see, it doesn't call the destructor of A.
The only way I see to get the destructor of A being called, is to add a destructor for the Interface class like this:

virtual ~Interface() { }

But I really want to avoid any Implementation in my Interface class and virtual ~Interface() = 0; doesn't work (produces some linker errors complaining about a non existing implementation of ~Interface().

So my question is: What do I have to change in order to make the destructor being called, but (if possible) leave the Interface as an Interface (only abstract methods).

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

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

发布评论

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

评论(3

尽揽少女心 2024-09-12 10:29:21

您必须在基类中定义虚拟析构函数,否则您将无法获得多态行为。

更重要的是,否则你会得到未定义的行为; §5.3.5/3:

如果操作数的静态类型与其动态类型不同,则静态类型应为操作数动态类型的基类,并且静态类型应具有虚拟析构函数,否则行为未定义.

强调我的。


我认为最好的是这个:

class Interface
{
public:
    virtual ~Interface(void) = 0;
};

inline Interface::~Interface(void) {}

编译器可以轻松内联它,这与实现驻留在源文件中的解决方案不同。 (说到这里,这个解决方案甚至不要求你有一个。)它也让类成为纯虚拟的。

You must define a virtual destructor in the base class, otherwise you'll get no polymorphic behavior.

And more importantly, you get undefined behavior otherwise; §5.3.5/3:

If the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined.

Emphasis mine.


I'd argue the best is this one:

class Interface
{
public:
    virtual ~Interface(void) = 0;
};

inline Interface::~Interface(void) {}

The compiler can easily inline this, unlike a solution where the implementation resides in a source file. (Speaking of which, this solution doesn't even mandate you have one.) It also leaves the class pure virtual.

三五鸿雁 2024-09-12 10:29:21

您需要定义 Interface 析构函数的纯虚拟版本,但还需要定义析构函数的主体。这是 C++ 中的一种奇怪情况,即使函数是虚拟的,也必须定义它,因为在调用 A 析构函数之后,也会调用 Instance 析构函数。

因此,正确的答案是:

virtual ~Interface() = 0;

然后,在 cpp 文件中:

Interface::~Interface() {}

You need to define a pure virtual version of the Interface destructor, but you need to also define the body of the destructor. This is a sort of weird case in C++ where even though the function is virtual it must be defined because after the A destructor is called, the Instance destructor will also be called.

Thus the correct answer is:

virtual ~Interface() = 0;

And later, in a cpp file:

Interface::~Interface() {}
无法言说的痛 2024-09-12 10:29:21

如果您想通过指向基类接口类型的指针删除派生类对象,则必须声明析构函数 virtual,并且该析构函数必须具有实现。

不过,您仍然可以将其声明为纯虚拟:

class Interface
{
public:
    virtual ~Interface() = 0;
};

inline Interface::~Interface() { }

You must declare the destructor virtual if you want to delete derived-class objects via a pointer to your base class interface type, and that destructor must have an implementation.

You may still declare it pure virtual, though:

class Interface
{
public:
    virtual ~Interface() = 0;
};

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