Undefined reference to 'vtable for xxx'
takeaway.o: In function `takeaway':
project:145: undefined reference to `vtable for takeaway'
project:145: undefined reference to `vtable for takeaway'
takeaway.o: In function `~takeaway':
project:151: undefined reference to `vtable for takeaway'
project:151: undefined reference to `vtable for takeaway'
takeaway.o: In function `gameCore':
project.h:109: undefined reference to `gameCore<int>::initialData(int)'
collect2: ld returned 1 exit status
make: *** [takeaway] Error 1
Je reçois cette Erreur de l'éditeur de liens , je sais qu'il a quelque chose à voir avec les fonctions inline obtenir une vtable stockés temporairement. Mais ce que cela implique, je ne suis pas tout à fait sûr. Je suppose qu'il a quelque chose à voir avec la façon dont je l'appelle gameCore du constructeur dans la liste des initilization takeaway.cpp
J'ai basé sur un modèle de classe (gameCore.h)
et une classe (takeaway.cpp) qui hérite de gameCore
La vtable d'erreur est appelé 3 fois
1)dans la vente à emporter constructeur
2) plats à emporter destructeur
3)dans gameCores constructeur
J'utilise G++
Voici le code:
(je sais que cela peut paraître dur à lire, mais j'ai marqué exatcly où les erreurs se produisent)
plats à emporter.h
#ifndef _TAKEAWAY_H_
#define _TAKEAWAY_H_
#include<map>
#include<cctype>
#include<stack>
#include<map>
#include<iostream>
#include<string>
#include<cstdlib>
#include"gameCore.h"
#include<vector>
using namespace std;
class takeaway : public gameCore<int>
{
private:
public:
//template<class Penny>
void textualGame();
bool isNum(string str);
//template<class Penny>
stack<int> initialData(int initial);
//template<class Position>
int score (int position);
//template<class Position>
stack<int> addStack(int currentPos, stack<int> possiblePositions);
//template<class Penny>
takeaway (int initial);
//template<class Position>
~takeaway();
};
bool isNum(string str);
int charToint(char *theChar);
#endif
takeaway.cpp
/*
Description :
This game communicates with the gameCore class to determine the results
of a game of takeaway played between two computers or a computer and human.
*/
#include "takeaway.h"
/*
Description:Creates a stack represening initial data
Note:Change to a vector eventually
return : stack of int
*/
stack<int> takeaway:: initialData(int initial){
stack<int> returnStack;
int theScore = score(initial);
int final;
if(initial ==0)
{
final = 1;
}
else
{
final = 0;
}
returnStack.push(theScore);
returnStack.push(final);
return returnStack;
}
/*
Description: a textual representation of the game
Note: This is still terribly wrong
*/
void textualGame(){
cout <<"this is the best i could do for a graphical representation";
}
/*
Description: Deetermines if a number is even
Note: Helper function for determining win or loss positions
Returns: 1 if it is and 0 if it is not
*/
int takeaway::score(int position){
if(position % 2 == 0)
{
return 1;
}
return 0;
}
/*
Description: Will return a stack , withouth the given postion in it
will contain all positions possible after the given position
along with anyother that wehre in the given stack.This function
Must also update the map to represent updated positions
Takes: a position to check and a stack to return
Returns: A stack of possible positions.
*/
stack<int> takeaway::addStack(int currentPos, stack<int> possiblePositions ){
if(currentPos != 0)
{
//If even
if( currentPos % 2 == 0)
{
//Create a data aray with score of the new positon and mark it as not final
int data[] = {score(currentPos/2),0};
vector<int> theData(data, data+sizeof(data));
int pos = currentPos/2;
//Add it to the map
//this -> gamesMap[currentPos/2] = dataArray;
this -> gamesMap.insert(std::pair<int, vector<int> >(pos, theData));
//Add it to the possible positions
possiblePositions.push(pos);
}
if(currentPos % 3 == 0)
{
int data[] = {score(currentPos/3),0};
vector<int> theData(data,data+sizeof(data));
int pos = currentPos/3;
//this -> gamesMap[currentPos/3] = dataArray;
this -> gamesMap.insert(std::pair<int, vector<int> >(pos, theData));
possiblePositions.push(pos);
}
//Work for the position that represents taking one penny
int minusFinal = 0;
if(currentPos - 1 == 0)
{
minusFinal = 1;
}
int data[] = {score(currentPos - 1),minusFinal};
vector<int> theData(data,data+sizeof(data));
int pos = currentPos - 1;
//this -> gamesMap[currentPos -1] = dataArary
this->gamesMap.insert(std::pair<int,vector<int> >(pos, theData));
possiblePositions.push(pos);
}
return possiblePositions;
}
/*
Description: Constructor for the takeaway game
OA takes: a initial position, and initial data for it
*/
takeaway::takeaway(int initial):gameCore<int>::gameCore(initial){ //<--- ERROR HERE
//Constructor
}
/*
Description: Destuctor
*/
takeaway::~takeaway(){ //<--------------------- ERROR HERE
//Destructor
}
//checks input and creates game.
int main(int argc, char* argv[]){
int numberPennies ;
string game = argv[0];
if(argc == 2 && isNum(argv[1]) )
{
int pennies = charToint(argv[1]);
takeaway gameInstance(pennies ); //Creates a instance of $
}
// else if(argc == 3 && argv[1] == "play" && isNum(argv[2]) )
//{
// int pennies = charToint(argv[2]);
// takeaway<int> gameInstance(pennies); //Craete a human playab$
//}
else
{
cerr << "Error->Usage: " << game <<" [play] numberOfPennies \n";
exit (1);
}
return 0;
}
//Converts a char to a integer
int charToint(char *theChar){
int theInt = atoi(theChar);
return theInt;
}
//Determines if a string is numeric
bool isNum(string str){
for(int i = 0;i < str.length() ;i++){
if(isdigit(str[i]) != 1)
{
cerr << "Error->Input: Number must be a Positive Integer the charecter '" << str[i]<< "' invalidated your input. \n" ;
exit(1);
return false;
}
}
return true;
}
gameCore.h
/*
gameCore.h
Description:
This class created gameMap that are written as a template
They will communicate with the specific game and the algorithm
To keep track of positions ans there values.
*/
#ifndef GAMECORE_H
#define GAMECORE_H
#include <map>
#include <stack>
#include <string>
#include <vector>
using namespace std;
template <class Position>
class gameCore
{
protected:
//Best Move used by algorithim
Position bestMove;
//The current highest score used by the algorithim
int highestScore ;
//Stack to be used to remmeber what move created the score
stack<Position> movedFrom;
//Stack used for the algorithim.
stack<Position> curWorkingPos;
//The actual Map that the data will be held in.
map<Position,vector<int> > gamesMap;
public:
/*
Description : finds the data array for a poisition
takes: a Position
Returns: a array of integers /**
*/
virtual stack<int> initialData(Position pos) = 0;
/*
Description: Game must implement a way to determine a positions
score.
*/
virtual int score(Position pos) = 0;
/*
Description: A Graphical representation of the game
*/
virtual void textualGame() = 0;
/*
Description: a virtual function implemented by the child class
it will return a stack without the given position in it.This stack
will contain all positions available from the given postion as well as
all position already in the given stack. Also it will update the map with
all generated positions.
TAkes: a postion to check and a stack of currently working positons.
*/
virtual stack<Position> addStack(Position currentPos, stack<Position> possiblePositions ) = 0;
/*
Description:Constructor that
Creates a Map with positions as the key.
And an array of two integers that represent the positions
value and if we have moved here in the past.
Takes: a Initial Position and a Array of integers
*/
gameCore(Position initial){ //<-----ERROR HERE
//Determine the initial data and add it to the map and queue.
stack<int> theData = initialData(initial);
int first = theData.top();
theData.pop();
int second = theData.top();
theData.pop();
int initialData[] = {first,second};
vector<int> posData(initialData,initialData+sizeof(initialData));
gamesMap[initial] = posData;
curWorkingPos.push(initial);
}
/*
Description:
A destructor for the class
*/
~gameCore(){
//I do nothing but , this class needs a destructor
}
/*
Description: Takes the current position and returns
that positions Score.
Takes: A position
Returns:A integer that is a positions score.
*/
int getPosScore(Position thePos) const {
return this ->gamesMap.find(thePos)->second[0];
}
/*
Description: Adds values to a stack based on the current position
Takes: a poistion
*/
void updateStack(Position curPos){
this ->curWorkingPos =addStack(curPos,this ->curWorkingPos ); //get a stack from the game
//The game has a function that takes a position and a stack and based on the positions returns a stack identical to the last but with added values that represent valid moves from the postion./
}
/*
Description : Takes a positions and returns a integer
that depends on if the position is a final pos or not
Takes: A position
Returns: A Bool that represents if the position is a final(1) or not (0).
*/
//Possible change
bool isFinal(Position thePos) {
typename map<Position,vector<int> >::iterator iter = this ->gamesMap.find(thePos);
return iter->second[1] == 1 ;
}
/*
Description: Based on the given position determine if a move needs to be made.
(if not this is a end game position and it will return itself) If a move needs
to be made it will return the position to move to that is ideal.
Note: (because all positions can be represented as integers for any game , the return
type is a integer)
*/
int evaluatePosition(Position possiblePosition ){
if(isFinal(possiblePosition)) //If this is a final position
{
return getPosScore(possiblePosition); //Return the score
}
else
{
updateStack(possiblePosition); //Put all possible positions from this in thte stack
while(this -> curWorkingPos.size() != 0)
{
this -> movedFrom.push(this->curWorkingPos.front()); //take the top of the possible positions stack and set it the the moved from stack
this -> curWorkingPos.pop();
int curScore = evaluatePosition(this ->movedFrom.top()); //Recursive call for school
curScore = curScore * -1; //Negate the score
if(curScore > this -> highestScore) //if the score resulting from this position is biggest seen
{
highestScore = curScore;
this ->movedFrom.pop(); //do this first to get rid of the the lowest point
this -> bestMove = this ->movedFrom.top(); //mark where the lowest point came from
}
else
{
this -> movedFrom.pop();
}
}
}
return this -> bestMove;
}
//A Structure to determine if a position has a lower value than the second
struct posCompare{
bool operator() (Position pos1,Position pos2) const {
return (pos1.getPosScore() < pos2.getPosScore());
}
};
};
#endif
- Vous avez besoin de poster un exemple, et pas seulement cracher tout votre code.
- C'est une bonne question, mais wayyyy à plus de code, essayez de la réduire un peu, de sorte que nous pouvons facilement comprendre ce qui se passe et le problème.
- Pouvez-vous essayer de réduire votre code sur un petit exemple qui reproduit le problème? Qui aidera les gens à vous aider. Et il peut même vous aider à vous comprendre vous-même. Et, heu, sont l'historique de la révision des commentaires vraiment nécessaire ici?
- Je voudrais seulement ajouter que, parfois, cette erreur se produit lorsque le destructeur de la classe dérivée n'a pas été défini.
- Mon dieu, comment cette question ont donc beaucoup de upvotes. Il serait sans doute servir les utilisateurs à mieux si il y avait juste le journal des erreurs et que la meilleure réponse serait la première phrase de @bdonlan 's réponse.
- Double Possible de Undefined reference to vtable
Vous devez vous connecter pour publier un commentaire.
La première série d'erreurs, le manque vtable, sont dues au fait que vous n'implémentez pas
takeaway::textualGame()
; au lieu de cela vous de mettre en œuvre un non-membre de la fonction,textualGame()
. Je pense que l'ajout de l'manquanttakeaway::
permettra de résoudre ce problème.La cause de la dernière erreur est que vous êtes à l'appel d'une fonction virtuelle,
initialData()
, à partir du constructeur degameCore
. À ce stade, les fonctions virtuelles sont distribués en fonction du type actuellement en cours de construction (gameCore
), pas la plupart de la classe dérivée (takeaway
). Cette fonction est virtuelle pure, et donc de l'appeler ici donne un comportement indéterminé.Deux solutions possibles:
gameCore
de l'constructeur et séparée en une initialisation de la fonction qui doit être appelée après l'objet est entièrement construit; ougameCore
en deux classes: une interface abstraite pour être mis en œuvre partakeaway
, et une classe de béton contenant de l'état. Construiretakeaway
d'abord, et ensuite de le passer (par l'intermédiaire d'une référence à la classe d'interface) pour le constructeur de la classe de béton.Je recommanderais le second, c'est d'aller vers des classes plus petites et un couplage lâche, et il sera plus difficile d'utiliser les classes de manière incorrecte. Le premier est plus enclin à l'erreur, comme il n'y a aucun moyen d'être sûr que l'initialisation de la fonction est appelée correctement.
Un dernier point: le destructeur d'une classe de base doit généralement être virtuel (pour permettre polymorphes suppression) ou de la protection (pour éviter les invalides polymorphes suppression).
gameCore::initialData()
qui n'a pas de mise en œuvre.gameCore::initialData()
, puisque c'est actif remplacer pendant le constructeur degameCore
. Il ne sait pas si cette fonction est mise en oeuvre ou pas, donc il ne peut pas générer une erreur à ce stade. L'éditeur de liens découvre que la fonction n'est pas implémentée, et génère l'erreur de nous voir.Un ou plusieurs de vos .fichiers cpp n'est pas lié à, ou de certains non-inline fonctions dans une classe ne sont pas définis. En particulier,
takeaway::textualGame()
's la mise en œuvre ne peut pas être trouvé. Notez que si vous avez défini untextualGame()
au niveau supérieur, mais ceci est distinct d'unetakeaway::textualGame()
mise en œuvre - sans doute vous avez juste oublié letakeaway::
là.Ce que l'erreur signifie que l'éditeur de liens ne pouvez pas trouver le "vtable" pour une classe - chaque classe avec des fonctions virtuelles a un "vtable" structure de données associée. Dans GCC, ce vtable est généré dans le même .fichier cpp que le premier non-inline membre de la classe; si il n'y a pas non en ligne membres, il sera généré partout où vous instancier la classe, je crois. Alors, vous êtes probablement à défaut de lien la .fichier cpp avec le premier de la liste non-inline membre, ou de ne jamais définir ce membre dans la première place.
Si une classe définit des méthodes virtuelles à l'extérieur de la classe, alors g++ génère la vtable uniquement dans le fichier d'objet qui contient l'extérieur-de-la définition de la classe de la méthode virtuelle qui a été déclarée d'abord:
La vtable sera dans test1.o, mais pas dans test2.o
C'est une optimisation de g++ implémente pour éviter d'avoir à les compiler dans la classe définie par des méthodes virtuelles qui seront tirés par la vtable.
L'erreur de lien vous décrire suggère que la définition d'une méthode virtuelle (str::f dans l'exemple ci-dessus) est manquant dans votre projet.
Vous pouvez prendre un coup d'oeil à cette réponse à une question identique (comme je le comprends):
https://stackoverflow.com/a/1478553
Le lien posté il explique le problème.
Rapide de la résolution de votre problème, vous devriez essayer de coder quelque chose comme ceci:
ImplementingClass::virtualFunctionToImplement(){...}
Il m'a beaucoup aidé.
il suggère que vous ne parviennent pas à lier le instancié explicitement basetype public gameCore (alors que le fichier d'en-tête de l'avant de la déclarer).
Puisque nous ne savons rien au sujet de votre config/dépendances de la bibliothèque, on ne peut pas vraiment dire qui le lien drapeaux/fichiers source sont absents, mais j'espère que le soupçon seul vous aide à résoudre ti.
Manquant de la mise en œuvre d'une fonction dans la classe
La raison que j'ai été confronté à ce problème était parce que j'avais supprimé la fonction mise en oeuvre à partir du fichier cpp, mais oublié de supprimer la déclaration de la .h fichier.
Ma réponse n'est pas de répondre spécifiquement à votre question, mais laisse les gens qui viennent à ce fil, à la recherche de la réponse de savoir que l'on peut aussi l'une des causes.