0

I have a parent class with a virtual function in it, I then make a child class and define the function. I then make a vector of vectors and insert one of the child classes into it. I then try to call the virtual function and nothing outputs to the screen. I do not know why this is happening, does anyone know?

Parent Class

class insect{
        public:
           string type;
           int food_cost;
           int armor;
           int damage;
           insect();
           void set_food_cost(int x);
           void set_armor(int x);
           void set_damage(int x);
           virtual void attack(){} // this is the problematic function


};

Child Class

class bee: public insect{
        public:
           bee();
           int armor;
           int damage;
           void set_armor(int x);
           void attack();


};

void bee::attack(){
        cout << "im a bee, stab stab!\n";
}

Creating Vector of Vectors

vector< vector<insect> > insects_on_board(10);

Adding a bee to the vector of vectors

void add_bee(vector< vector<insect> > &insects_on_board, int &bees){
        bees++;
insects_on_board[9].push_back(bee());
}

Function Call

cout << "testing " << insects_on_board.at(9).at(0).type << endl;
        insects_on_board.at(9).at(0).attack();

Output

testing B

My Question Again

so in the output im expecting to see "testing B" and then "im a bee, stab stab!"

but only the "testing B" is outputted to the screen, any ideas why the other part is not?

billy
  • 13
  • 3
  • You might want to search for 'slicing' – JVApen May 26 '18 at 06:25
  • 1
    Your vector contains insects, not bees. – melpomene May 26 '18 at 06:28
  • @Sneftel not a duplicate, first time asking this question – billy May 26 '18 at 06:28
  • Apart from being a duplicate, this question also lacks a [mcve]. – melpomene May 26 '18 at 06:30
  • @melpomene this is true, but bee is an insect, so anything an insect can do a bee should be able to do. and my vector at [0][9] is no longer an insect it should be a bee, which is proven when I test the type. – billy May 26 '18 at 06:30
  • this is not a duplicate, once again this is not a duplicate...may be similar question but look at the code, totally different...plus that other question was asked 4 years ago – billy May 26 '18 at 06:31
  • @billy Nowhere in your code do you test the type. And you don't need to test anything because you can just look at the declaration: `vector< vector >` says this is a vector of insects. Not bees. – melpomene May 26 '18 at 06:31
  • @billy The code is doing exactly the same thing: putting a `Derived` into a container of `Base`s and expecting them to still be `Derived`s. – Sneftel May 26 '18 at 06:33
  • @melpomene I do test the type of insect in my code, right before I call the virtual function. and once again bee is derived from insect so it should have access to all of insects public functions. – billy May 26 '18 at 06:34
  • This is a duplicate, once again this is a duplicate (by which I mean, don't bother repeating yourself, it doesn't help with anything). Look at the code: It has a `vector` and OP expects to be able to call a virtual method in `DerivedClass` on it, but the `BaseClass` version is called. Exactly the same as yours. And what does it matter that someone else had your problem 4 years ago? – melpomene May 26 '18 at 06:35
  • @billy `foo.type` accesses a member variable called `type`; it does not actually check the type. (And because your code is not a [mcve], we can't see how you set `type` anyway.) It doesn't matter what `bee` does or how it's derived; your code (at least the part you've shown us) uses objects of class `insect`, not `bee`. – melpomene May 26 '18 at 06:36
  • @melpomene it matters because the person from 4 years ago wasn't dealing with what im currently dealing with – billy May 26 '18 at 06:36
  • 1
    Please explain why you think that "*the person from 4 years ago wasn't dealing with what im currently dealing with*". You're kind of ignoring the part where I told you why we think it's the same problem: "*It has a `vector` and OP expects to be able to call a virtual method in `DerivedClass` on it, but the `BaseClass` version is called.*". How is that not the same issue? – melpomene May 26 '18 at 06:39
  • @melpomene im sorry for the confusion, ive added the add_bee function to my above code. im pretty sure im inserting bee objects into my vector, so why is the attack function not working? – billy May 26 '18 at 06:41
  • Dude. All of that is answered in the duplicate question. In your particular code you're doing `.push_back(bee())`. `bee()` creates a `bee`, but `.push_back` takes an `insect`, so the `bee` object is implicitly converted to an `insect`, then copied to the vector (because you declared your vector as consisting of `insect` objects). It's a bit like doing `vector v; v.push_back(sqrt(2.0));` and wondering why `v[0]` is just `1`. – melpomene May 26 '18 at 06:45
  • @melpomene ok I understood that clearly, thank you. so I thought I was pushing a bee but really I was converting it into an insect. so how to fix this? hmmm, should I create a temp bee object and then push that into the vector? or would that just do the same thing? thank you for all your help – billy May 26 '18 at 06:49

1 Answers1

0

That's because you are storing actual insects and not any bees. Polymorphism (in its basic C++ way) works when you are doing 3 things:

  1. Have a type hierarchy with properly defined and overridden virtual methods (like you are doing here,)
  2. Create child instances (or a variety of parent and child instances,)
  3. Access them through pointers (or references.)

You are missing points 2 and 3.

So, one way to fix it would be to store pointers to insect, and initialize them as either bees or plain insects, like so:

vector<vector<insect *>> insects_on_board (10, vector<insect *>(2)); // note the type
insects_on_board[9][0] = new bee;
insects_on_board[9][1] = new insect;

// Note the use of "->" instead of "."
cout << "testing " << insects_on_board[9][0]->type << endl;
insects_on_board[9][0]->attack();

// Contrast the output with the above's
cout << "testing " << insects_on_board[9][1]->type << endl;
insects_on_board[9][1]->attack();

Update: Note that (at the basic level) any container that stores insects by value cannot contain anything else; not even classes derived from insect. All the polymorphism and stuff you read and hear about is only applicable for pointers to parent and child types (or references to them.)

So, your add_bee function should look like this:

void add_bee (vector<vector<insect *>> & insects_on_board, int & bees) {
    bees++;
    insects_on_board[9].push_back(new bee());
}

I've made only two changes in there: the vectors now contain pointers to insect and I'm newing the bees.

yzt
  • 8,873
  • 1
  • 35
  • 44
  • ok ive added my add_bee function above, so I believe I was doing number 2 on your list. so is it just number 3 that is causing me problems? – billy May 26 '18 at 06:43
  • @billy No, you were not. In `add_bee`, you are making a temporary `bee`, which is *casted* to an insect and pushed back into your vector. I'll update my answer. – yzt May 26 '18 at 06:44