2010-12-04 37 views
0

J'ai essayé de trouver quel est le problème de cette partie de code suivante. J'ai écrit une classe d'exception personnalisée où j'ai une classe de base pour les erreurs de pile, et puis certaines classes qui en dérivent sont appelées stack_full_error. J'ai un problème pour le compiler, j'ai l'erreur suivante.Erreur de référence de symbole C++

Undefined      first referenced 
symbol        in file 
stack_error::~stack_error()   /var/tmp//ccFwZ5Kd.o 
ld: fatal: Symbol referencing errors. No output written to a.out 
collect2: ld returned 1 exit status 

Cela dit quelque chose à propos du destructeur, et j'ai essayé de le réparer, sans succès. Quoi qu'il en soit, j'espère que quelqu'un pourra me dire quel est le problème.

class stack_error : public exception 
{ 
public: 
    stack_error(string const& m) throw() 
     : exception(), msg(m) {}; 
    virtual ~stack_error() throw() =0; 
    virtual const char* what() const throw() 
    { 
     return msg.c_str(); 
    } 

private: 
    string msg; 
}; 

class stack_full_error : public stack_error 
{ 
public: 
    stack_full_error() throw() 
     : stack_error("Exception: stack full") {}; 
    ~stack_full_error() throw() {}; 
}; 

Et là où j'appelle l'exception pour cette première fois

template <class T> 
void Stack<T>::push(T i) 
{ 
    if(is_full()) 
     throw stack_full_error(); 

    this->first = new Node<T>(this->first, i); 
    amount++; 
} 

Répondre

2

virtuelle pure ou non, stack_error doit définir son destructor, car il est appelé implicitement stack_full_error destructor. Vous devez ajouter:

stack_error::~stack_error() {} 

dans un fichier d'implémentation.

+0

douce résolu le problème, ne savait pas que vous deviez définir destructeur, mais il est fait virtuel pur. – starcorn

1

Vous ne pouvez pas avoir un destructor abstrait. Vous devez le définir dans stack_error. (voir la correction ci-dessous)

Vouliez-vous faire en virtuel?

Contrairement à d'autres fonctions virtuelles, les destructeurs virtuels ne se chevauchent pas les uns les autres. Les destructeurs de toutes les classes de base seront exécutés séquentiellement (à partir du destructeur de classes le plus dérivé). Chaque classe doit avoir un destructeur; Même si vous ne définissez pas de destructeur, il est créé implicitement.

Correction:
Vous pouvez faire l'abstrait destructor, mais il faut définir son corps de toute façon. Comme ceci:

virtual ~stack_error() = 0 {}; 

si ceci est votre compilateur les dernières fonctionnalités de C++ 0x. Sinon, vous devez définir le corps extérieur:

class stack_error 
{ 
    ... 
    virtual ~stack_error() = 0; 
    ... 
}; 
stack_error::~stack_error() {} 

Résumé (=0) signifie qu'il doit être dans les classes définit dérivés; Néanmoins, vous devez définir le corps du destructeur.

+0

les fonctions virtuelles pures peuvent ne pas avoir une définition en ligne, et je ne suis pas sûr que C++ 0x change cela – icecrime

+0

@icecrime: bien, AFAIK au C++ 0x ce sucre syntaxique est permis. Je ai vérifié avec mon compilateur actuel, il ne permet toujours pas cela :-(. – Vlad

0

Je ne suis pas sûr que les destructeurs peuvent (devraient?) Être abstraits. Destructors should be virtual mais je me souviens d'avoir des problèmes quand ils étaient abstraits.

+1

Destructeurs * peut * être virtuel pur, mais doit avoir une implémentation même si elle l'est.Vous pouvez le faire pour forcer la classe à être abstraite quand elle n'a pas d'autres fonctions virtuelles pures, bien que je ne puisse pas penser à une raison pour vouloir le faire. –