簡體   English   中英

模板指針 class 可以有虛擬析構函數嗎?

[英]Can a templated Pointer class have a virtual destructor?

在使用自制指針 class 實現 pimpl 習語時,我遇到了一個令人驚訝的啟示(我知道:為什么要自己動手?但請耐心等待)。 以下三個文件包含一個最小示例:

指針.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;
};

富.h:

#pragma once
#include "Pointer.h"

struct Foo
{
    Foo();
    ~Foo();

private:
    void operator=(const Foo&);
    Foo(const Foo&);

private:
    Pointer<struct FooPrivate> p;
};

主.cpp:

#include "Foo.h"

int main(int argc, char* argv[])
{
    Foo foo;
    return 0;
}

別介意Foo.cpp的內部結構是什么樣的。 當我使用 MSVC 2008 編譯main.cpp時,我收到警告:

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>派生,並且新的 object 可以從FooPrivate未完全定義的某個地方被銷毀。 編譯器不肯定你不這樣做,所以它會發出警告。 在這種微不足道的情況下,您可以放心地忽略它,但如果您確實需要虛擬析構函數,那么將它牢記在心可能是個好主意。

由於您正在為 class Foo提供析構函數,因此警告似乎完全不正確和虛假。

只是為了檢查我是否在文件 [foo.cpp] 中添加了此代碼:

#include "foo.h"
#include <iostream>
using namespace std;

struct FooPrivate
{
    FooPrivate() { cout << "FooPrivate::<init>" << endl; }
    ~FooPrivate() { cout << "FooPrivate::<destroy>" << endl; }
};

Foo::Foo()
    : p( new FooPrivate )
{
    cout << "Foo::<init>" << endl;
}

Foo::~Foo()
{
    cout << "Foo::<destroy>" << endl;
}

這產生了與您得到的相同的警告(使用 Visual C++ 10.0),但是 output

FooPrivate::<初始化>
Foo::<初始化>
Foo::<銷毀>
FooPrivate::<銷毀>

顯然,可執行文件並沒有像愚蠢的警告所說的那樣......

干杯&hth.,

在不競爭的類型上調用delete是未定義的行為。

因為您沒有給出FooPrivate的完整定義,所以編譯器不知道它的 vtable 是什么樣的。 由於它無法調用它無法定位的虛擬 function,它保釋了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM