2016-08-04 6 views
0

У меня возникла проблема создания экземпляра дочернего класса в родительском.C++ singleton create child в родительском классе

Вот определение одноточечного (родительский класс)

db.hpp 
------- 
#ifndef DB_HPP 
#define DB_HPP 

#include <string> 
#include "mysqldb.hpp" 

class Db 
{ 
    public: 
    static Db& instance() 
    { 
     // can be added other database implementations 
     #ifdef DBMYSQL 
     static Db *instance = new MySQLDb(); 
     #elseif DBORACLE 
     //static Db *instance = new OracleDb(); 
     #endif 
     return *instance; 
    } 

    virtual ~Db() {} 
    virtual void Insert(std::string& query) = 0; 
    protected: 
    Db() {} 
}; 
#endif // DB_HPP 

и здесь ребенок

mysqldb.hpp 
----------- 
#ifndef MYSQLDB_HPP 
#define MYSQLDB_HPP 

#include "db.hpp" 
#include <mysql.h> 

class MySQLDb : public Db 
{ 
    public: 
    virtual void Insert(std::string& query); 

    private: 
    MYSQL *MySQLConnection_; 
    MySQLDb(); 
    ~MySQLDb(); 
}; 
#endif // MYSQLDB_HPP 

я получил ошибку ожидал типа Спецификатор до того 'MySQLDb'

g++ -DDBMYSQL `mysql_config --cflags` `mysql_config --libs` -DBOOST_LOG_DYN_LINK -std=c++11 -c -o mysqldb.o mysqldb.cpp 

In file included from mysqldb.hpp:4:0, 
      from mysqldb.cpp:1: 
db.hpp: In static member function ‘static Db& Db::instance()’: 
db.hpp:16:35: error: expected type-specifier before ‘MySQLDb’ 
    static Db *instance = new MySQLDb(); 
          ^
Makefile:39: recipe for target 'mysqldb.o' failed 

Вы не знаете, что случилось?

+0

У вас есть круговая зависимость mysqldb.hpp включает db.hpp, который включает в себя mysqldb.hpp, который включает в себя db.hp .... нет другого выбора, кроме изменения вашего дизайна. – Garf365

+0

Базовый класс должен знать о дочернем классе сделай один. Детский класс должен создать базовый класс при его построении. Кроме того, это синглтон, так что вы не можете. Так что ребенок тоже должен быть синглом. И вы делаете только один из них. Я мог бы решить это. Но я бы предпочел: нет (очевидной) причины для базового класса быть одиночным. Если вы просто хотите, просто сделайте это. В общем, вы не можете использовать singleton как базовый класс. – doctorlove

+0

Вам действительно нужно включить весь файл, а не просто объявление в db.hpp? – YiFei

ответ

1

Прежде всего у вас есть циклическая зависимость (что является причиной ошибки в токе вы получаете): Db зависит от MySQLDb, которая зависит от Db и так далее навсегда.

Это очень легко решить: Включите файл заголовка "mysqldb.hpp"после вы определили в Db класс. Затем переместите определение Db::instance за пределы класса, но не забудьте явно отметить его inline. Из исходного файла, где вы реализуете функцию Db::instance, и только вперед объявите класс MySQLDb в заголовочном файле "db.hpp2", не включите файл "mysqldb.hpp".

После этого, что у вас будет еще одна проблема, а именно, что MySQLDb конструктор частный и Db класс не может получить доступ к нему. Это можно решить, сделав Db a friend от MySQLDb.


Однако все это, круговая зависимость и делает Dbfriend является признаком плохого дизайна, ИМ.

Я мог бы вместо этого сделать что-то вроде Db чистого абстрактного класса и переместить фабричную функцию в другое место. Возможно, используя шаблоны.

Одиночки и наследование редко играют вместе.

Кроме того, что, если вы хотите иметь несколько одновременных соединений? Возможно, в разные базы данных разных типов? Нельзя использовать шаблон singleton.

Смежные вопросы