Dog dog;
Animal* animal = &dog;
cout << dog.sound() << animal->sound() << endl;
//gives output "barkbark"
// where as
Animal animal_2 = dog;
cout << animal_2.sound();
//output "animal sound"
while
Animal& animal_3 = dog;
cout << animal_3.sound();
//output "bark"
//WHY do animal_2 and animal_3 give different output???
So what's really the thing with virtual functions? As far as I understand it gives you the opportunity to store an address of a daughter-class in a mother-class pointer, but still call the daugther-class member function. Correct?
And why is the output different in my animal_2 and animal_3 example?
So what's really the thing with virtual functions? As far as I understand it gives you the opportunity to store an address of a daughter-class in a mother-class pointer, but still call the daugther-class member function. Correct?
The pointers are stored in a virtual function table. Actually an array where each constructor [re]places the addresses of the virtual functions.
And why is the output different in my animal_2 and animal_3 example?
animal_2 contains the [partial] copy of the content of dog (not the virtual function table), while animal_3 is the refernce to dog.
This constructs an Animal object from a Dog object. Since animal_2 is an Animal object and not a Dog object calling sound() on this object will call the Animal::sound() member function. It's called object slicing because only the Animal parts of the Dog object will be copied which is usually not what you want. To avoid this you might want to disable copying of the Animal class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
class Animal {
public:
Animal() = default;
Animal(const Animal&) = delete; // disable the copy constructor
Animal& operator=(const Animal&) = delete; // disable the copy assignment operator
virtual string sound() {
return"animal sound";
}
};
...
Animal animal_2 = dog; // error: use of deleted function ‘Animal::Animal(const Animal&)’
animal_3 is a reference to an object. When you call a virtual function it will look up the correct function using the dynamic type of the object that the reference is referring to (not the static type of the reference). The pointer example (Animal* animal = &dog;) works the same way.
animal_2 does not refer to another object. It is an object, and its type is Animal, so that is why it will just call Animal::sound().
If Animal::sound() is not declared virtual, will it always call Animal::sound() if Animal is the type of the pointer/reference (i.e. it will follow the type the pointer/reference it is declared as, rather than the type of the object it is assigned to?)