Ho un errore di collegamento in cui il linker si lamenta che il distruttore della mia classe concreta chiama il distruttore astratto della superclasse, il cui codice manca.Errore linker: desidera il distruttore di classe base virtuale C++
Questo sta utilizzando GCC 4.2 su Mac OS X da XCode.
Ho visto g++ undefined reference to typeinfo ma non è esattamente la stessa cosa.
Ecco il messaggio di errore di linker:
Undefined symbols:
"ConnectionPool::~ConnectionPool()", referenced from:
AlwaysConnectedConnectionZPool::~AlwaysConnectedConnectionZPool()in RKConnector.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
Ecco l'abstract dichiarazione di classe di base:
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;
};
Ecco la dichiarazione della classe concreta:
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);
};
Inutile dire , tutti quei membri sono implementati. Qui è il distruttore:
AlwaysConnectedConnectionZPool::~AlwaysConnectedConnectionZPool()
{
printf("AlwaysConnectedConnectionZPool destructor call"); // nothing to destruct in fact
}
e forse anche la routine di fabbrica:
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);
}
posso risolvere questo problema artificialmente facendo la mia classe di base astratta concreta. Ma preferirei fare qualcosa di meglio. Qualche idea?
Grazie
La risposta implica questo, ma vale la pena sottolineare che nei metodi astratti C++ * può * avere implementazioni. Sono stato sinceramente sorpreso quando ho scoperto, prima ho sempre pensato a metodi come astratti o di implementazione, non entrambi. – sbk
@sbk Che non è corretto. In C++ abstract significa _pure_ virtual. Una funzione _non-pure_ virtual non è astratta, né rende astratta la sua classe. – Zimano
@Zimano: quale parte del mio commento non è corretta? Sono d'accordo che "puro virtuale" e "astratto" sono la stessa cosa. Stavo dicendo che in C++ astratto/metodi virtuali puri * può * avere corpi/implementazione e distruttori, anche astratti, * deve * averne uno. Cioèil snippet '' 'classe A {virtuale ~ A() = 0 {}}' '' è valido – sbk