简体   繁体   中英

C++ Forward declaration and pure virtual functions

I have a problem using forward declaration and virtual functions. I got the following error message during compilation.

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> > > >&)

The compiler said these functions are still pure virtual functions, but I declared and defined them properly. I don't know what the problem is.

Here is my source code.

// 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)
{
    ...
}

Thank you.

Because of the forward declaration compiler is looking for the class QueryResult in the global namespace. The function you defined in class MySQL use the inner class (which is inside the namespace) QueryResult . This is treated as an overloading by the compiler and not as the implementation of the pure virtual function. My suggestion to solve this is to remove the forward declaration and make the QueryResult a inner class of interface Interface (it makes sense to put it there, otherwise there is no use of the interface). Then it will compile properly.

move the decl "QueryResult" into the namespace Database::Interface

it seems to be an issue with name spaces.

You can probably do a quick fix now by making QueryResult a class and deriving MySQLQueryResult from it. As others pointed out the issue is with compiler not being able to use a nested class instead of the forward declared class.

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

        };

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