2010-08-10 38 views
2

J'ai un problème en utilisant la déclaration directe et les fonctions virtuelles. J'ai reçu le message d'erreur suivant lors de la compilation.C++ Déclaration avant et fonctions virtuelles pures

main.cpp:131: error: cannot allocate an object of abstract type ‘Database::MySQL’ 
database_mysql.h:31: note: because the following virtual functions are pure within ‘Database::MySQL’: 
database.h:28: note: virtual void Database::Interface::query(const char*, QueryResult&) 
database.h:29: note: virtual void Database::Interface::query(std::string, QueryResult&) 
database.h:30: note: virtual bool Database::Interface::step(QueryResult&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&) 

Le compilateur a dit que ces fonctions sont encore des fonctions virtuelles pures, mais je déclare et les a définis correctement. Je ne sais pas quel est le problème.

Voici mon code source.

// database.h 
class QueryResult; 

namespace Database 
{ 
    class Interface { 
     public: 
      Interface() {}; 
      virtual ~Interface() {}; 

      virtual void query(const char *sql) = 0; 
      virtual void query(std::string sql) = 0; 
      virtual void query(const char *sql, QueryResult &result) = 0; 
      virtual void query(std::string sql, QueryResult &result) = 0; 
      virtual bool step(QueryResult &result, 
           std::vector<std::string> &row) = 0; 
    }; 
} 

// database_mysql.h 
namespace Database 
{ 
    class MySQL : public Interface { 
     public: 
      class QueryResult { 
      public: 
       QueryResult(); 
       ~QueryResult() ; 
       void set(MYSQL_RES *result); 
       MYSQL_RES *get(); 

      private: 
       MYSQL_RES *_result; 

      }; 

      ... 

      void query(const char *sql); 
      void query(std::string sql); 
      void query(const char *sql, QueryResult &result); 
      void query(std::string sql, QueryResult &result); 
      bool step(QueryResult &result, std::vector<std::string> &row); 

      ... 
    }; 
} 


// database_mysql.cpp 
Database::MySQL::QueryResult::QueryResult() 
    : _result(NULL) 
{ 
} 

Database::MySQL::QueryResult::~QueryResult() 
{ 
    ... 
} 

void Database::MySQL::QueryResult::set(MYSQL_RES *result) 
{ 
    ... 
} 

MYSQL_RES *Database::MySQL::QueryResult::get() 
{ 
    ... 
} 


void Database::MySQL::query(const char *sql) 
{ 
    ... 
} 

void Database::MySQL::query(std::string sql) 
{ 
    ... 
} 

void Database::MySQL::query(const char *sql, QueryResult &result) 
{ 
    ... 
} 

void Database::MySQL::query(std::string sql, QueryResult &result) 
{ 
    ... 
} 

/* @return: false on done or true if remained rows exist */ 
bool Database::MySQL::step(QueryResult &result, std::vector<std::string> &row) 
{ 
    ... 
} 

Merci.

+0

Vous devez montrer ce qui est à main.cpp: 131 afin que nous puissions vous aider. Votre classe concrète est correctement définie, mais je suppose que vous n'instanciez pas l'objet correctement. En outre, comme indiqué par @anders, votre classe QueryResult doit appartenir au fichier Interface.h. –

+0

@Edison Gustavo Muenz: Cette erreur peut être reproduite en essayant de créer une instance de la classe 'Database :: MySQL' – Naveen

Répondre

1

déplacer le décl « QueryResult » dans l'espace de noms Base de données :: Interface

il semble être un problème avec des espaces de noms.

+0

Merci pour votre réponse. Cependant, le problème est toujours resté avec les mêmes messages d'erreur. – Brian

3

En raison du compilateur de déclaration directe recherche la classe QueryResult dans l'espace de noms global. La fonction que vous avez définie dans la classe MySQL utilise la classe interne (qui se trouve dans l'espace de noms) QueryResult. Ceci est traité comme en surchargeant par le compilateur et non comme l'implémentation de la fonction virtuelle pure. Ma suggestion pour résoudre ceci est de supprimer la déclaration avant et de faire le QueryResult une classe interne de l'interface Interface (il est logique de le mettre là, sinon il n'y a pas d'utilisation de l'interface). Ensuite, il compilera correctement.

+0

Merci. hmmm ... J'ai utilisé la déclaration forward pour faire qu'il y ait différentes classes QueryResult qui dépendent des API SQL comme database_sqlite3.h, etc. Mais je pense que ce n'est pas possible si je mets la classe QueryResult dans la classe Interface. – Brian

+0

Vous pouvez probablement faire de 'QueryResult' aussi une classe de base abstraite afin que l'implémentation différente de' Interface' puisse fournir leur propre implémentation de 'QueryResult'? – Naveen

+0

Merci, je vais essayer maintenant, mais comment puis-je recevoir un autre handle de base de données dans les paramètres de la fonction membre de la classe de base abstraite? Dois-je utiliser le pointeur void ou la classe de modèle? Désolé pour ma mauvaise question. Je suis un débutant C++. :-) – Brian

0

Vous pouvez probablement faire une solution rapide maintenant en faisant de QueryResult une classe et en en dérivant MySQLQueryResult. Comme d'autres l'ont souligné, le problème est que le compilateur ne peut pas utiliser une classe imbriquée à la place de la classe déclarée en avant.

 // database.h 
     class QueryResult { 
     //make this class abstract by creating a protected default constructor 
     protected: 
      QueryResult(){} 
     } 

     //mysql.cpp 
     class QueryResult : ::QueryResult { 
     public: 
      QueryResult(); 
      ~QueryResult() ; 
      void set(MYSQL_RES *result); 
      MYSQL_RES *get(); 

     private: 
      MYSQL_RES *_result; 

     }; 
+0

Est-il possible d'appeler des fonctions de MySQLQueryResult en utilisant la référence QueryResult? Comment puis-je déclarer des paramètres MySQLQueryResult sur les fonctions membres de l'interface sans déclarations directes? – Brian

+0

Votre classe de base 'QueryResult' devrait contenir des membres applicables à toutes les implémentations de' Interface', donc 'QueryResult' devrait contenir les fonctions/attributs les moins communs du dénominateur. –