当用自制的指针类实现pimpl成语时,我遇到了一个惊人的启示(我知道:为什么要自己滚动?但请耐心等待).以下三个文件包含一个最小示例:
Pointer.h:
#pragma once 
template <typename T>
class Pointer
{
public:
    Pointer(T*p=0)
        : _p(p)
    {
    }
    virtual ~Pointer()
    {
        delete _p;
    }
private:
    void operator=(const Pointer&);
    Pointer(const Pointer&);
private:
    T*_p;
};
foo.h中:
#pragma once
#include "Pointer.h"
struct Foo
{
    Foo();
    ~Foo();
private:
    void operator=(const Foo&);
    Foo(const Foo&);
private:
    Pointer<struct FooPrivate> p;
};
main.cpp中:
#include "Foo.h"
int main(int argc, char* argv[])
{
    Foo foo;
    return 0;
}
别介意内脏的Foo.cpp样子.当我main.cpp使用MSVC 2008 编译时,我收到警告:
pointer.h(13) : warning C4150: deletion of pointer to incomplete type 'FooPrivate'; no destructor called
通过从Pointers析构函数中删除关键字virtual可以避免警告.
这对我来说毫无意义.这个警告是合法的,还是MSVC编译器中的错误?如果是这样,我可以安全地忽略警告吗?
我知道在这种情况下使析构函数虚拟是没有意义的,但请记住,这只是一个最小的可编译示例.我原来的代码要复杂得多.
如果没有virtual,则只有一处将调用析构函数;在 之内~Foo,此时您大概已经完全定义了FooPrivate。如果在其他地方创建了另一个实例Pointer<FooPrivate>,您可能会收到警告,但由于您没有这样做,编译器可以告诉您的行为是安全的。
使用virtual,理论上您可以从 派生Pointer<FooPrivate>,并且可以从未完全定义的地方销毁该新对象FooPrivate。编译器不确定您不这样做,因此会发出警告。在这种微不足道的情况下,您可以放心地忽略它,但如果您确实需要虚拟析构函数,那么认真考虑它可能是个好主意。
| 归档时间: | 
 | 
| 查看次数: | 2460 次 | 
| 最近记录: |