简体   繁体   中英

Linker error: wants C++ virtual base class destructor

I have a link error where the linker complains that my concrete class's destructor is calling its abstract superclass destructor, the code of which is missing.

This is using GCC 4.2 on Mac OS X from XCode.

I saw g++ undefined reference to typeinfo but it's not quite the same thing.

Here is the linker error message:

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

Here is the abstract base class declaration:

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

Here is the concrete class declaration:

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

Needless to say, all those members are implemented. Here is the destructor:

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

and also maybe the factory routine:

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

I can fix this by artificially making my abstract base class concrete. But I'd rather do something better. Any idea?

Thanks

Even if you declare a destructor as a pure virtual function, you must provide an implementation for it. Although you cannot instantiate an abstract class directly, it is always instantiated when you instantiate one of its derived (concrete) classes. And so at some point such instances will be destroyed, thus requiring a destructor. The implementation of the pure virtual destructor can be (and normally is) an empty function:

ConnectionPool::~ConnectionPool() {
}

Even in an abstract class, you don't want your destructor to be pure virtual. That's because it is going to get called when a concrete subclass' destructor is called.

We use the following pattern.

foo.h

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

foo.cpp

AbstractBaseClass::~AbstractBaseClass() {
}

See this FAQ for details .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM