0

Given:

class AlbumDataService
{
public:
    explicit AlbumDataService(QSqlDatabase& database);
    void init() const;

    void addAlbum(Album& album) const;
    void updateAlbum(const Album& album) const;
    void removeAlbum(int id) const;
    std::unique_ptr<std::vector<std::unique_ptr<Album>>> albums() const;

private:
    QSqlDatabase& mDatabase;
};

AlbumDataService::AlbumDataService(QSqlDatabase& database) :
    mDatabase(database)
{

}

I'm confused as to why the following will leave mDatabase, in the above code, null

class DatabaseManager
{
public:
    static void debugQuery(const QSqlQuery& query);

    static DatabaseManager& instance();
    ~DatabaseManager();

    const AlbumDataService albumService;

protected:
    DatabaseManager(const QString& path = DATABASE_FILENAME);
    DatabaseManager& operator =(const DatabaseManager& rhs);

private:
    std::unique_ptr<QSqlDatabase> mDatabase;

};

But not in this case:

class DatabaseManager
{
public:
    static void debugQuery(const QSqlQuery& query);

    static DatabaseManager& instance();
    ~DatabaseManager();

protected:
    DatabaseManager(const QString& path = DATABASE_FILENAME);
    DatabaseManager& operator =(const DatabaseManager& rhs);

private:
    std::unique_ptr<QSqlDatabase> mDatabase;

public:
    const AlbumDataService albumService;
};

Even though the implementation of DatabaseManager(const QString& ); doesn't change between the two

DatabaseManager::DatabaseManager(const QString& path) :
    mDatabase(new QSqlDatabase(QSqlDatabase::addDatabase("QSQLITE"))),
    albumService(*mDatabase)
{
    mDatabase->setDatabaseName(path);

    bool openStatus = mDatabase->open();
    qDebug() << "Database connection: " << (openStatus ? "OK" : "Error");

    albumService.init();
}
m7913d
  • 10,244
  • 7
  • 28
  • 56
Scott
  • 11,046
  • 10
  • 51
  • 83
  • 1
    See http://stackoverflow.com/questions/6308915/member-fields-order-of-construction – juanchopanza Mar 05 '17 at 07:25
  • Also http://stackoverflow.com/questions/2669888/c-initialization-order-for-member-classes – juanchopanza Mar 05 '17 at 07:28
  • Most compilers will generate a warning about the different order of initialisation; something like "warning: `mDatabase` will be initialized after `albumService`" – m7913d Mar 05 '17 at 08:19

1 Answers1

1

When classes are constructed, the order of construction is firstly, to initialise any base classes, then to initialise the data members in the order they appear in the class definition. The order they appear in the constructors' initialisation lists is not considered.

This rigid rule makes sense because syntactically, there's nothing wrong with initialising data members and then calling the base class' constructor, yet could lead to havoc.

Seeing as your public albumService member requires a fully constructed mDatabase, you unfortunately will have to arrange them in the less-sightly way you have in the second class definition.

RobbieE
  • 4,280
  • 3
  • 22
  • 36
  • A better solution may be to make both private and add a getter function for `albumService`. – m7913d Mar 05 '17 at 08:27