13

具体的なクラスのデストラクタがその抽象スーパークラスのデストラクタを呼び出しており、そのコードが欠落しているとリンカーが不平を言うリンク エラーがあります。

これは、XCode から Mac OS X で GCC 4.2 を使用しています。

typeinfo への g++ 未定義の参照を見ましたが、まったく同じではありません。

リンカーのエラー メッセージは次のとおりです。

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);
}

これは、抽象的な基本クラスを人為的に具象化することで修正できます。しかし、私はむしろ何か良いことをしたいです。何か案が?

ありがとう

4

2 に答える 2

39

デストラクタを純粋仮想関数として宣言した場合でも、その実装を提供する必要があります。抽象クラスを直接インスタンス化することはできませんが、その派生 (具象) クラスの 1 つをインスタンス化すると、常にインスタンス化されます。そのため、ある時点でそのようなインスタンスは破棄されるため、デストラクタが必要になります。純粋仮想デストラクタの実装は、空の関数にすることができます (通常はそうです):

ConnectionPool::~ConnectionPool() {
}
于 2010-03-31T17:20:31.170 に答える
5

抽象クラスであっても、デストラクタを純粋仮想にしたくはありません。これは、具体的なサブクラスのデストラクタが呼び出されたときに呼び出されるためです。

次のパターンを使用します。

foo.h

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

foo.cpp

AbstractBaseClass::~AbstractBaseClass() {
}

詳細については、このFAQ を参照してください

于 2010-03-31T17:47:37.500 に答える