Eduard Morecat
Eduard Morecat

Reputation: 27

C++ std::vector with values from multiple classes

I'm using std::vector for storing my values into MyValues from my classes A and B. Inserted elements/values depends on the type of class. If it's A, inserts {x, y}, if B, inserts {x, y, z}. And I loop it, so i can try to add multiple values of it, to just test it. But when I loop A.ases 5 times and then B.bses 7 times, looped MyValues has 31 single elements for some reason. Is possible to add elements and "preserve forms" (If it's A -> {x, y}, if B, -> {x, y, z}), so I can get same values, like the ones I inserted and work with it?

classes:

std::vector<int> MyValues;

class A {
public:
    short int x, y;
    A() {
        this->x = this->y = 0;
    }
};

class B : public A{
public:
    short int z;
    B() {
        this->z = 0;
    }
};

main:

int main() {
    A ases[5];
    B bses[7];
    for (short int a = 0; a < 5; a++) {
        ases[a].x = 5 + a;
        ases[a].y = 4 + a;
        MyValues.insert(MyValues.end(), { ases[a].x, ases[a].y });
    }
    for (short int b = 0; b < 7; b++) {
        bses[b].x = 2 + b;
        bses[b].y = 3 + b;
        bses[b].z = 1 + b;
        MyValues.insert(MyValues.end(), { bses[b].x, bses[b].y, bses[b].z });
    }
    for (int v : MyValues) std::cout << "x y z = " << v << std::endl;
    return 0;
}

output:

x y z = 5
x y z = 4
x y z = 6
x y z = 5
x y z = 7
x y z = 6
x y z = 8
x y z = 7
x y z = 9
x y z = 8
x y z = 2
x y z = 3
x y z = 1
x y z = 3
x y z = 4
x y z = 2
x y z = 4
x y z = 5
x y z = 3
x y z = 5
x y z = 6
x y z = 4
x y z = 6
x y z = 7
x y z = 5
x y z = 7
x y z = 8
x y z = 6
x y z = 8
x y z = 9
x y z = 7

Upvotes: 0

Views: 564

Answers (2)

Adrian Mole
Adrian Mole

Reputation: 51815

You could make your MyValues a vector of vectors, like this:

std::vector<std::vector<int>> MyValues;

Then, without changing the definitions of your A and B classes, you can insert 2- or 3-element vectors, using much the same code as you already have in your main function. You would only need to change the way you display the data; I have shown one way, in the code below, but there are many others, depending on how 'pretty' you want your output to be.

int main()
{
    A ases[5];
    B bses[7];
    for (short int a = 0; a < 5; a++) {
        ases[a].x = 5 + a;
        ases[a].y = 4 + a;
        MyValues.insert(MyValues.end(), { ases[a].x, ases[a].y });
    }
    for (short int b = 0; b < 7; b++) {
        bses[b].x = 2 + b;
        bses[b].y = 3 + b;
        bses[b].z = 1 + b;
        MyValues.insert(MyValues.end(), { bses[b].x, bses[b].y, bses[b].z });
    }

    // No change required up to here; just change the code for output...
    for (auto v : MyValues) {
        std::cout << "{ ";
        bool first = true;
        for (auto i : v) {
            if (!first) std::cout << ", ";
            std::cout << i;
            first = false;
        }
        std::cout << " }" << std::endl;
    }
    return 0;
}

Output from above:

{ 5, 4 }
{ 6, 5 }
{ 7, 6 }
{ 8, 7 }
{ 9, 8 }
{ 2, 3, 1 }
{ 3, 4, 2 }
{ 4, 5, 3 }
{ 5, 6, 4 }
{ 6, 7, 5 }
{ 7, 8, 6 }
{ 8, 9, 7 }

Upvotes: 1

Tony Tannous
Tony Tannous

Reputation: 14856

If you are using visual studio 2019 then you should be able to turn on C++17. This demo uses std::optional. Not sure how efficient it is, but it's convenient.

#include <iostream>
#include <vector>
#include <optional>

struct Base
{
    int x, y;
    std::optional<int> z;
    Base(int _x, int _y) : 
        x(_x),
        y(_y)
        {} 
    
    Base(int _x, int _y, int _z) : 
        x(_x),
        y(_y),
        z(_z)
        {} 
};

int main()
{
    Base b1 {1, 2, 3};
    Base b2 {4, 5};
    Base b3 {9, 9, 9};

    std::vector V {b1, b2, b3};

    for (auto& item : V)
    {
        std::cout << item.x << " " << item.y << " ";
        if (item.z.has_value()) 
            std::cout << item.z.value();
        std::cout << std::endl;
    }
}

And for demo: https://godbolt.org/z/nbedjb

Upvotes: 2

Related Questions