user4206969
user4206969

Reputation: 7

c++ singleton create child in parent class

I have problem to create instance of child class in parent one.

Here is definition of singleton (parent class)

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

and here is the child

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

I got error expected type-specifier before ‘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

Do you have any idea what's wrong?

Upvotes: 0

Views: 400

Answers (1)

Some programmer dude
Some programmer dude

Reputation: 409136

First of all you have a circular dependency (which is the reason behind the current error you get): Db depends on MySQLDb which depends on Db and so on forever.

This is very easy to solve: Include the "mysqldb.hpp" header file after you defined the Db class. Then move the definition of Db::instance outside of the class, but remember to explicitly mark it inline. Of have a source file where you implement the Db::instance function, and only forward declare the MySQLDb class in the "db.hpp2" header file, not include the "mysqldb.hpp" file.

After doing that you will have another problem, namely that the MySQLDb constructor is private and the Db class can't access it. This can be solved by making Db a friend of MySQLDb.


However all of this, the circular dependency and making Db a friend is a sign of a bad design, IMO.

I might instead do something like having Db a pure abstract class, and move the factory-function somewhere else. Maybe using templates.

Singletons and inheritance seldom play well together.

Furthermore, what if you want to have multiple simultaneous connections? Perhaps to different databases of different kinds? Can't use the singleton pattern then.

Upvotes: 1

Related Questions