简体   繁体   中英

C++ how to load from file array of pointers to objects?

I have an abstract class Object, which looks like this:

class Object
{
public:
    Object();
    virtual void DoSomething() = 0;
    virtual void Save(std::ofstream &file) = 0;
    virtual void Load(std::ifstream &file) = 0;
};

I also have classes Ball and TextBox:

class Ball : public Object
{
public:
    Ball(int x, int y, int z)
    {
        m_x = x; m_y = y; m_z = z;
    }

    void DoSomething()
    {
        std::cout << m_x << ", " << m_y << ", " << m_z << std::endl;
    }
    void Save(std::ofstream &file)
    {
        file << m_x << " " << m_y << " " << m_z << std::endl;
    }
    void Load(std::ifstream &file)
    {
        file >> m_x >> m_y >> m_z;
    }

private:
    int m_x, m_y, m_z;
};
class TextBox: public Object
{
public:
    TextBox(std::string message)
    {
        m_message = message;
    }

    void DoSomething()
    {
        std::cout << m_message << std::endl;
    }
    void Save(std::ofstream &file)
    {
        file << m_message << std::endl;
    }
    void Load(std::ifstream &file)
    {
        file >> m_message;
    }

private:
    std::string m_message;
};

I have a vector of pointers to theese objects:

std::vector<Object*> objects;
objects.push_back(new Ball(1, 2, 3));
objects.push_back(new TextBox("Hello world!"));

for (Object *o : objects) o->DoSomething();

I want to save this vector to file. This is very easy. I make something like this:

std::ofstream file("foo.txt");
for (Object *o : objects) o->Save(file);
file.close();

Now I want to load this. And here is a problem. How I can specify, which object (Ball or TextBox) I supposed to load? I could use some indexes, like that:

void Ball::Save(std::ofstream &file)
{
    file << 1 << " " << m_x << " " << m_y << " " << m_z << std::endl;
}
void TextBox::Save(std::ofstream &file)
{
    file << 2 << " " << m_message << std::endl;
}

Then, after reading this index, I know, that this is a Ball or a TextBox.

int index;
Object *o;

file >> index;
switch (index)
{
case 1: o = new Ball(0, 0, 0); break;
case 2: o = new TextBox(""); break;
}
o->Load(file);
objects.push_back(o);

But is there a better way to store this structure? What if I have 100 inheritors of Object? Can I somehow avoid 100-switch case?

These 'indexes' you came up with are usually called 'metadata'. There are other languages, like java, that support reflection for that purpose but in C++ reflection in still under consideration. For that reason, I would suggest implementing sort of an abstract interface that would return information of the exact class of an object.

Furthermore, I would suggest looking at serialization libraries, that could ease the process of saving and reading data. You can try to start with boost: https://www.boost.org/doc/libs/1_73_0/libs/serialization/doc/index.html

I must admit that I used boost serialization a long time ago, but I remember it was quite easy to use.

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