Venelin
Venelin

Reputation: 3308

C++ How to place data in vector of base class

Here is my base class:

#include <string>
#include "DataStruct.h"
#include <vector>
#include <mysqlx/xdevapi.h>
#include <iostream>
#include <memory>

namespace Vibranium {
    using namespace mysqlx;
    class MySQLTable {
    public:
        MySQLTable();
        virtual ~MySQLTable() = default;
        int Index;
        std::string tableName;
        DataStruct dataStruct;
        std::vector<std::unique_ptr<DataStruct>> Data;
        Table getTable(Session& conn) const;
        RowResult getAll(Session& conn) const;
        virtual void LoadTable(RowResult& res) {}
    };
}

#endif //VIBRANIUM_CORE_MYSQLTABLE_H

Which is representing all MySQL tables i might have. Take a look at Data vector of types DataStruct. I use DataStruct as a base struct because all tables will have different structure.

Here is base DataStruct struct:

namespace Vibranium{
    struct DataStruct{};
}

Than I define my first mysql tablle Accounts:

#include <string>
#include "Database/DataStruct.h"
#include "Database/MySQLTable.h"


namespace Vibranium{
    using namespace std;
    struct AccountsStruct : DataStruct{
        int id;
        std::string email;
        std::string warTag;
        int state;
        std::string name;
        std::string lastname;
        std::string country;
        int dob_month;
        int dob_day;
        int dob_year;
        double balance;
        std::string created_at;
        std::string updated_at;
        int account_role;
        int rank;
        int playerRole;
    };


    class Accounts : public MySQLTable{
    public:
        Accounts() = default;
        void LoadTable(RowResult& res) override;
    };

}

As you can see inside I have defined AccountsStruct as child of DataStruct. Here is how I implement LoadTable:

#include "Accounts.h"

using namespace Vibranium;

void Vibranium::Accounts::LoadTable(RowResult &res) {

        std::vector<AccountsStruct> accounts;
        AccountsStruct accountsStruct;
        for (Row row : res.fetchAll()){
            accountsStruct.id = row[0].get<int>();
            accountsStruct.email = row[1].get<std::string>();
            accountsStruct.warTag = row[2].get<std::string>();
            accountsStruct.state = row[4].get<int>();
            accountsStruct.name = row[5].get<std::string>();
            accountsStruct.lastname = row[6].get<std::string>();
            accountsStruct.country = row[7].get<std::string>();
            accountsStruct.dob_month = row[8].get<int>();
            accountsStruct.dob_day = row[9].get<int>();
            accountsStruct.dob_year = row[10].get<int>();
            accountsStruct.balance = row[11].get<double>();
            accountsStruct.created_at = row[12].get<std::string>();
            accountsStruct.updated_at = row[13].get<std::string>();
            accountsStruct.account_role = row[15].get<int>();
            accountsStruct.rank = row[16].get<int>();
            accountsStruct.playerRole = row[17].get<int>();
            accounts.push_back(accountsStruct);
        }
}

As Accounts is child of MySQLTable

  1. I would like to add all the data from std::vector<AccountsStruct> accounts into Data vector inherited from MySQlTable.
  2. Also after that I would like to cycle thru the vector Data as it is of type Accounts instead of MySQLTable class. However I don't know how can I achieve those two things.

Is it possible and how?

Upvotes: 0

Views: 90

Answers (2)

Caleth
Caleth

Reputation: 62566

I would drop the type DataStruct, and make MySqlTable a template.

#include <string>
#include <vector>
#include <mysqlx/xdevapi.h>
#include <memory>

namespace Vibranium {
    using mysqlx::Table;
    using mysqlx::RowResult;
    using mysqlx::Session;

    class MySQLTableBase {
    public:
        MySQLTableBase();
        virtual ~MySQLTableBase() = default;
        Table getTable(Session& conn) const;
        RowResult getAll(Session& conn) const;

        int Index;
        std::string tableName;
    };

    template <typename T>
    class MySQLTable : public MySQLTableBase {
    public:
        virtual void LoadTable(RowResult& res) = 0;

        T dataStruct; // What is this?
        std::vector<T> Data; // You don't need vector of pointers
    };
}

Then you define Account and Accounts as

#include <string>
#include "Database/MySQLTable.h"

namespace Vibranium{
    struct Account{
        int id;
        std::string email;
        std::string warTag;
        int state;
        std::string name;
        std::string lastname;
        std::string country;
        int dob_month;
        int dob_day;
        int dob_year;
        double balance;
        std::string created_at;
        std::string updated_at;
        int account_role;
        int rank;
        int playerRole;
    };

    class Accounts : public MySQLTable<Account>{
    public:
        Accounts() = default;
        void LoadTable(RowResult& res) override;
    };
}

Upvotes: 2

Evgeny
Evgeny

Reputation: 1072

So, have fun with C++!

  1. You don't have a vector in MySQLTable with name "Data". You have method (Data) returning vector of ... To implement your request you should create method (for example) void SetData(...).

  2. You can't. You can cycle through vector of Data and cast (for example static_cast, or other) each element from Data to AccountStruct. WARNING! Wrong cast operation may cause undefined behavior, crashes, etc.!

Upvotes: 0

Related Questions