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

时间:2010-06-15 23:29:07

标签: c++ abstract-class destructor virtual-functions

我对以下代码有疑问:

#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()的非现有实现。

所以我的问题是:为了使析构函数被调用,我需要更改什么,但是(如果可能的话)将接口作为接口(仅抽象方法)。

3 个答案:

答案 0 :(得分:5)

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

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

  

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

强调我的。


我认为最好的是这个:

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

inline Interface::~Interface(void) {}

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

答案 1 :(得分:2)

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

你仍然可以宣称它是纯虚拟的:

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

inline Interface::~Interface() { }

答案 2 :(得分:2)

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

因此,正确的答案是:

virtual ~Interface() = 0;

后来,在一个cpp文件中:

Interface::~Interface() {}