Ошибка компоновщика: хочет C++ виртуальный деструктор базового класса

У меня есть ошибка ссылки, где компоновщик жалуется, что деструктор моего реального класса называет свой абстрактный деструктор суперкласса, код которого отсутствует.

Это использует GCC 4.2 на Mac OS X от XCode.

Я видел g ++ неопределенная ссылка на 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:
    
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);
}

Я могу зафиксировать это путем искусственного создания моего бетона абстрактного базового класса. Но я сделал бы что-то лучше. Какая-либо идея?

Спасибо

8
задан Community 23 May 2017 в 02:07
поделиться

2 ответа

Даже если вы объявляете деструктор как чистую виртуальную функцию, вы должны предоставить для него реализацию. Хотя вы не можете создать экземпляр абстрактного класса напрямую, он всегда создается, когда вы создаете экземпляр одного из его производных (конкретных) классов. И поэтому в какой-то момент такие экземпляры будут уничтожены, что потребует деструктора. Реализация чистого виртуального деструктора может быть (и обычно является) пустой функцией:

ConnectionPool::~ConnectionPool() {
}
34
ответ дан 3 November 2019 в 12:40
поделиться

Даже в абстрактном классе вы не хотите, чтобы ваш деструктор был чисто виртуальным. Это потому, что он будет вызываться при вызове деструктора конкретного подкласса.

Мы используем следующую схему.

foo.h

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

foo.cpp

AbstractBaseClass::~AbstractBaseClass() {
}

Подробности см. В FAQ .

4
ответ дан 3 November 2019 в 12:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: