vendredi 18 avril 2014

héritage - confusion de méthode virtuelle C++ - Stack Overflow


I have a basic C++ question about inheritance and virtual methods.


Please regard this code:


#include <iostream>
#include <vector>
using namespace std;

class A {
public:
virtual void f() {cout << "A\n";};
};

class B : public A {
public:
void f() {cout << "B\n";};
};

int main() {
A a;
B b;
vector<A> v;
v.push_back(a);
v.push_back(b);

for (int i = 0; i < v.size(); ++i)
v.at(i).f();
}

If I execute this code, it prints out


A
A

I do not understand why it does not print


A
B

because the "f" method is declared as virtual. I would like to know why the program behaves in this way.


Thanks in advance




Your vector contains A objects:


vector<A> v;

when you push_back a B object into it, the vector copies the A part of it into a new A object. It is the equivalent of doing this:


A a;
B b;
a = b;
a.f();

This is called object slicing.




You are slicing the object, you need to use pointers or references for this to behave properly. Example using pointers:


int main()
{
vector<A*> v;
v.push_back(new A);
v.push_back(new B );

for (int i = 0; i < v.size(); ++i)
v[i]->f();
}

This will give you the polymorphic behavior you wanted and will have this output:


A
B



b is sliced to an instance of A when it's copied for insertion into the vector, you would have to use vector<A*> for this to work as you expect.




You should have vector of pointers in order to have polymorphic behavior :)




In C++, only pointers and references to objects behave polymorphically. Your vector contains non polymorphic objects of type A.


try


int main() {
A a;
B b;
vector<A*> v;
v.push_back(&a);
v.push_back(&b);

for (int i = 0; i < v.size(); ++i)
v.at(i)->f();

Though you need to be aware that those pointers will become invalid when a and b are destroyed (when they go out of scope).




The vector v contains Objects for Type A. When you push back objects to v these objects are instantiated using the copy constructor of A. Like that each of the objects you call later on the function f for is actually of type A and will never execute B's f().



I have a basic C++ question about inheritance and virtual methods.


Please regard this code:


#include <iostream>
#include <vector>
using namespace std;

class A {
public:
virtual void f() {cout << "A\n";};
};

class B : public A {
public:
void f() {cout << "B\n";};
};

int main() {
A a;
B b;
vector<A> v;
v.push_back(a);
v.push_back(b);

for (int i = 0; i < v.size(); ++i)
v.at(i).f();
}

If I execute this code, it prints out


A
A

I do not understand why it does not print


A
B

because the "f" method is declared as virtual. I would like to know why the program behaves in this way.


Thanks in advance



Your vector contains A objects:


vector<A> v;

when you push_back a B object into it, the vector copies the A part of it into a new A object. It is the equivalent of doing this:


A a;
B b;
a = b;
a.f();

This is called object slicing.



You are slicing the object, you need to use pointers or references for this to behave properly. Example using pointers:


int main()
{
vector<A*> v;
v.push_back(new A);
v.push_back(new B );

for (int i = 0; i < v.size(); ++i)
v[i]->f();
}

This will give you the polymorphic behavior you wanted and will have this output:


A
B


b is sliced to an instance of A when it's copied for insertion into the vector, you would have to use vector<A*> for this to work as you expect.



You should have vector of pointers in order to have polymorphic behavior :)



In C++, only pointers and references to objects behave polymorphically. Your vector contains non polymorphic objects of type A.


try


int main() {
A a;
B b;
vector<A*> v;
v.push_back(&a);
v.push_back(&b);

for (int i = 0; i < v.size(); ++i)
v.at(i)->f();

Though you need to be aware that those pointers will become invalid when a and b are destroyed (when they go out of scope).



The vector v contains Objects for Type A. When you push back objects to v these objects are instantiated using the copy constructor of A. Like that each of the objects you call later on the function f for is actually of type A and will never execute B's f().


0 commentaires:

Enregistrer un commentaire