Fill vector with different class

Hey guys, i have this problem in my programe: I want to create a vector something like vector <animal> a; where the class animal is abstract. So i don't know if i can declare a vector of this abstract class and then fill it with the derivatives classes, and then use them in my code. Something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <string>
#include <vector>

using namespace std;

class animal //base
{
public:
    animal(): age (0){}
    ~animal(){}
    void setage(int _age) {age=_age;}
    
    int getage() {return age;}
    
    virtual void move()=0;
private:
    int age;
};

class horse : public animal
{
public:
    horse (){}
    ~horse(){}
    void move() { }
};

int main()
{
    horse h;
    //animal *a[6];
    //a[0]=&h;

    //vector <animal> a (6);
    //a.assign(1,h);
}


I don't know if i can do this, that's why i didn't implement that last part in my code, but there are two options that i could do.
Last edited on
You can't put abstract classes in a vector, but you can put pointers of abstract classes in a vector.

vector <animal *> animal(6);
@Thomas1965 thanks you for the answer
Do you know how could i put derivatives classes on that vector that you have declared, or should i assign the pointers from the vector to the derivatives classes?

1
2
3
4
5
6
animal *pa1 = NULL;
vector <animal *> animal(6);
animal.push_back (pa1);
//code
horse h;
animal[0]=&h;


1
2
3
horse h;
vector <animal *> animal(6);
animal.push_back(h);


Been horse derived class and animal abstract class.
I would do like this way:
1
2
3
4
5
6
7
8
9
int main()
{
  vector <animal *> animals(6);

  horse *newHorse = new horse;

  animals.push_back(newHorse);
    
}
Do you really need any nulls in the vector?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main()
{
  vector <animal *> animals; // empty vector

  horse *newHorse = new horse;

  animals.push_back(newHorse);

  // use

  for(size_t i = 0; i < animals.size(); ++i)
  {
    delete animals[i];
  }
  animals.clear(); // a bt redundant as exiting, but...
}


And you don't need new (or delete) if you're working with a limited set of animals;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int main()
{
  vector <animal *> animals; // empty vector

  Horse horse[2];
  Cat   cat[2];
  Dog   dog[2];
  // etc

  // all animals must exist for longer than the animals vector
  // so new/delete approach is safer in general
  animals.push_back(&horse[0]);
  animals.push_back(&horse[1]);
  animals.push_back(&cat[0]);
  animals.push_back(&cat[1]);
  animals.push_back(&dog[0]);
  animals.push_back(&dog[1]);
  // etc
}


Andy

PS using a smart pointer would be better than a raw pointer
Last edited on
Thank you.

Do you know how can i print a variable from an objetc which is inside the vector:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Piece
{
public:
    Piece (char _letter) : letter (_letter), colorP (true) {}
    ~Piece(){}
    void setletter(char _letter) {letter =_letter;}
    void setcolorP (bool _colorP) {colorP = _colorP;}

    char getletter() {return letter;}
    int getcolorP () {return colorP;}

    virtual void  posicion ()=0;
    virtual void  mover()=0;

private:
    char letter;
    bool colorP;
};

class rook : virtual public Piece
{
public:
    rook (char _letter) : Piece (_letter){}
    ~rook (){}
    void mover() { }
    void posicion() {}
};

class knight : virtual public Piece
{
public:
    knight (char _letter) : Piece (_letter){}
    ~knight(){}
    void mover() { }
    void posicion() {}
};

//... rest of the classes


int main(){

    knight c ('c');
    rook t ('t');
    
    vector <Piece*> p (6);
    p.push_back(&t);
    p.push_back(&c);
    cout <<"letter "<< p(2)->getletter(); //here is the compilation problem. i want to print the char a
}
This why we always tell people DON'T DOUBLE POST. I've already answered your question in your other thread.

Please don't double post.
And don't forget that you're using push_back() on a vector that already has 6 elements.

Edit: and those 6 elements are uninitialized.
Last edited on
Sorry. I didn't know where to post these because it was something related.

My programe finish when i change p(2)->getletter(); to p[1]->getletter() i don't know why
If you're still having problems, read my last post. What is the first element that has initialized data? Hint it is not element 1 or 2.
> vector <Piece*> p (6);
creates a vector with 6 elements

> p.push_back(&t);
add one element, so now it has 7 elements.


> here is the compilation problem
¿what compilation problem? ¿what error messages?
¿what do I even need to ask you to provide that information?
Thanks for the answers, but i have a new problem: i want to print a full bidimensional array with a for but i cant do it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <string>
#include  <vector>

using namespace std;

class Piece
{
public:
    Piece () : letter ('o') {}
    ~Piece(){}
    void setletter(char _letter) {letter =_letter;}

    char getletter() {return letter;}

    virtual void  move()=0;

private:
    char letter;
};


int main(){
    
   Piece *table [8][8];
    char _letter = 'o';
    int i=0, j=0;
    table[i][j]->setletter(_letter);    //here is a warning that says: 'table [i][j]' is not used uninitualized in this function
    cout << table[i][j]->getletter();   //i can print this
    cout <<endl<< "table full of 'o': "<< endl<<endl;
    for (i=0; i<8; i++){ cout <<endl;
       for (j=0; j<8; j++){
            table[i][j]->setletter(_letter);
            cout << table[i][j]->getletter();   //but not this
        }
    }
}


I can print just 1 by 1 the elements of my array but not everyone in just once.
Line 25: You've created an 8x8 array of pointers, not Pieces. Those pointers are uninitialized.

Line 28,29,33,34: You're trying to use the pointer at table[i][j] which is garbage.

Get rid of the * on line 25 and change your references from -> to .

Edit: Based on your earlier post with derived classes, Rook and Knight, I'm guessing you do want pointers (for polymoprphism). You will need to initialize the array of pointers in some manner (perhaps setting empty cells to nullptr). In any case, you will need to be careful to only reference those cells that have valid pointers to Pieces.


Last edited on
@AbstractionAnon thank you. You said it in your edit, i can't use Pieces, i have to use pointers because Pieces is abstract. But i don't know why i can print line 28 and 29 but not the 'for (31, 32, 33 and 34), it just finishes my program, maybe because I'm trying to print garbage which is not what i want.
Why did you change to using an array from the vector? You had almost everything correct, except the fact that you declared a vector with 6 uninitialized elements and tried to access some of these uninitialized elements causing the program to crash.
Because i want to fill the table, which is bidimensional array of pointers, with the elements from the vector. Then print table[i][j]->getletter(); with 'o' where there is no Piece and the letter from the Piece when it's busy.

I have Piece *table [8][8]; vector<Piece *> p; which i dont have any problem any more, and char _letter = 'o';.

I want to see in my terminal something like:

oooooooooo
oooooooooo
oooooooooo
oooooooooo
oooooooooo
oooooooooo
oooooooooo
oooooooooo

and then

tcadract
pppppppp
oooooooo
oooooooo
oooooooo
oooooooo
pppppppp
tcadract
Last edited on
As I indicated before, you need to initialize the array. The pointers are currently uninitialized (garbage).

Since your default constructor for Piece initializes letter to 'o', you can simply create 64 Piece instances.
1
2
3
  for (int i=0; i<8; i++
    for (int j=0; j<8; j++)
      table[i][j] = new Piece;

If this is a chess board, shouldn't there just be 32 pieces?

The chess board has 64 squares, of course.

Andy

PS vector <Piece*> p (6);

does not create a vector of six uninititalized elements; the elements are value initialized (if no constructor is avaliable) or default constructed (it there is a default constructor.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Msg {
private:
    std::string m_text;
public:
    Msg(const char* pszText = nullptr)
    : m_text((pszText == nullptr) ? "Hello, world!" : pszText) {}
    const std::string& getText() const {
        return m_text;
    }
};

int main() {
    std::vector<void*> checkPtr(6);
    std::vector<Msg>   checkMsg(4);

    for(size_t i = 0; i < checkPtr.size(); ++i)
        cout << checkPtr[i] << "\n";
    cout << "\n";

    for(size_t i = 0; i < checkMsg.size(); ++i)
        cout << checkMsg[i].getText() << "\n";
    cout << "\n";

    return 0;
}


00000000
00000000
00000000
00000000
00000000
00000000

Hello, world!
Hello, world!
Hello, world!
Hello, world!
Last edited on
Topic archived. No new replies allowed.