2010-03-31 107 views
5

我有一個鏈接錯誤,其中連接器抱怨我的具體類的析構函數正在調用其抽象超類析構函數,其代碼丟失。鏈接器錯誤:想C++虛擬基類析構函數

這是在XCode的Mac OS X上使用GCC 4.2。

我看到了g++ undefined reference to typeinfo但它不是完全相同的東西。

這裏是接頭錯誤消息:

Undefined symbols: 
    "ConnectionPool::~ConnectionPool()", referenced from: 
     AlwaysConnectedConnectionZPool::~AlwaysConnectedConnectionZPool()in RKConnector.o 
ld: symbol(s) not found 
collect2: ld returned 1 exit status 

這裏是抽象基類聲明:

class ConnectionPool { 
public: 
    static ConnectionPool* newPool(std::string h, short p, std::string u, std::string pw, std::string b); 
    virtual ~ConnectionPool() =0; 
    virtual int keepAlive() =0; 
    virtual int disconnect() =0; 
    virtual sql::Connection * getConnection(char *compression_scheme = NULL) =0; 
    virtual void releaseConnection(sql::Connection * theConnection) =0; 
}; 

這裏是混凝土類聲明:

class AlwaysConnectedConnectionZPool: public ConnectionPool { 
protected: 
    <snip data members> 
public: 
    AlwaysConnectedConnectionZPool(std::string h, short p, std::string u, std::string pw, std::string b); 
    virtual ~AlwaysConnectedConnectionZPool(); 
    virtual int keepAlive(); // will make sure the connection doesn't time out. Call regularly 
    virtual int disconnect(); // disconnects/destroys all connections. 
    virtual sql::Connection * getConnection(char *compression_scheme = NULL); 
    virtual void releaseConnection(sql::Connection * theConnection); 
}; 

不用說,所有這些成員都得到執行。這裏是析構函數:

AlwaysConnectedConnectionZPool::~AlwaysConnectedConnectionZPool() 
{ 
    printf("AlwaysConnectedConnectionZPool destructor call"); // nothing to destruct in fact 
} 

,也或許工廠例行:

ConnectionPool* ConnectionPool::newPool(std::string h, short p, std::string u, std::string pw, std::string b) 
{ 
    return new AlwaysConnectedConnectionZPool(h, p, u, pw, b); 
} 

我可以人爲地讓我的抽象基類,具體解決此問題。但我寧願做更好的事情。任何想法?

感謝

回答

28

即使你聲明析構函數作爲一個純虛函數,你必須爲它的實現。雖然你不能直接實例化一個抽象類,但是當你實例化一個派生(具體)類時,它總是被實例化。所以在某些情況下,這些實例將被破壞,因此需要析構函數。純虛析構函數的實現可以(而且通常是)一個空函數:

ConnectionPool::~ConnectionPool() { 
} 
+2

您的回答暗示,但值得強調的是,在C++中,抽象方法*可以具有實現。當我發現時,我真的很驚訝,在此之前,我一直認爲方法不是抽象的就是有實現,而不是兩者。 – sbk 2010-03-31 17:32:30

+0

@sbk這是不正確的。在C++中抽象意味着_pure_虛擬。一個_non-pure_虛函數不是抽象的,也不是抽象的。 – Zimano 2016-01-07 11:40:16

+0

@Zimano:我評論的哪部分內容不正確?我同意「純虛擬」和「抽象」是一回事。我在說,在C++中,抽象/純虛擬方法*可以具有body/implementation和destructor,即使是抽象的,也必須具有一個。即片段'''class A {virtual〜A()= 0 {}}'''是有效的 – sbk 2016-01-13 12:44:32

5

即使是一個抽象類,你不想讓你的析構函數是純虛函數。這是因爲在調用具體子類的析構函數時它會被調用。

我們使用以下模式。

foo.h中

class AbstractBaseClass { 
public: 
    virtual ~AbstractBaseClass(); 
    virtual void method1() = 0; 
    virtual void method2() = 0; 
protected: 
    AbstractBaseClass() { 
    } 
}; 

Foo.cpp中

AbstractBaseClass::~AbstractBaseClass() { 
} 

看到這個FAQ for details

+0

你確實希望它是純虛擬的,你只需要提供一個實現。此外,您發佈的鏈接不涉及純粹的虛擬析構函數。 – 2010-03-31 17:50:11

+1

@MPG:有時候你想要聲明一個抽象基類(一個不能被實例化),但是你發現你的自己沒有虛函數 - 你總是可以聲明你是析純函數的純虛函數 - 然後就像Neil說的那樣有一個實現(我不知道我是否意識到)。 – quamrana 2010-03-31 18:07:44

+1

@ Neil:如果抽象基類有其他純粹的虛擬方法,那麼dtor沒有特別的理由也是純粹的(就我所知,無論如何)。正如你所提到的,它需要有一個實現。考慮到這兩個前提,dtor應該不是一個純粹的虛擬方法 - 我會質疑這個類的唯一純虛擬方法是dtor的基本原理。 – 2010-03-31 18:20:26