I have a little problem with polymorphism. My simple code:
Animal.h
class Animal {
public:
Animal();
Animal(const Animal& orig);
virtual ~Animal();
virtual void get();
};
Animal.cpp
#include "Animal.h"
#include <iostream>
using namespace std;
Animal::Animal() {
cout << "Animal is born" << endl;
}
void Animal::get() {
cout << "get() from an Animal!" << endl;
}
Bird.h
class Bird : public Animal {
public:
Bird();
Bird(const Bird& orig);
virtual ~Bird();
void get();
};
Bird.cpp
#include "Bird.h"
#include <iostream>
using namespace std;
Bird::Bird() {
cout << "Bird is born" << endl;
}
void Bird::get() {
cout << "get() from a Bird!" << endl;
}
Chicken.h
#include "Bird.h"
class Chicken : public Bird {
public:
Chicken();
Chicken(const Chicken& orig);
virtual ~Chicken();
void get();
};
Chicken.cpp
#include "Chicken.h"
#include <iostream>
using namespace std;
Chicken::Chicken() {
cout << "Chicken is born" << endl;
}
void Chicken::get() {
cout << "get() from a Chicken!" << endl;
}
There is also a factory method returning an Animal* pointer to the concrete implementation based on input:
Factory.h
#include "Animal.h"
#include "Bird.h"
class Factory {
public:
Factory();
Factory(const Factory& orig);
virtual ~Factory();
Animal* generateAnimal();
Bird* generateBird();
};
Factory.cpp
#include "Factory.h"
#include "Animal.h"
#include "Bird.h"
#include "Chicken.h"
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
Animal* Factory::generateAnimal() {
string choice;
cout << "What do you want? 1-Animal, 2-Bird, 3-Chicken" << endl;
cin >> choice;
Animal* animal;
if (choice.at(0) == '1') {
cout << "You chose Animal" << endl;
animal = new Animal();
return animal;
} else if (choice.at(0) == '2') {
cout << "You chose Bird" << endl;
animal = new Bird();
return animal;
} else if (choice.at(0) == '3') {
cout << "You chose Chicken" << endl;
animal = new Chicken();
return animal;
} else {
cout << "Wrong input" << endl;
exit(1);
}
}
Bird* Factory::generateBird() {
string choice;
cout << "What do you want? 1-Animal, 2-Bird, 3-Chicken" << endl;
cin >> choice;
Bird* bird;
if (choice.at(0) == '2') {
cout << "You chose Bird" << endl;
bird = new Bird();
return bird;
} else if (choice.at(0) == '3') {
cout << "You chose Chicken" << endl;
bird = new Chicken();
return bird;
} else {
cout << "Wrong input" << endl;
exit(1);
}
}
I omitted ctors & dtors.
main.cpp
#include <cstdlib>
#include <iostream>
#include "Factory.h"
#include "Animal.h"
#include "Bird.h"
#include "Chicken.h"
using namespace std;
int main(int argc, char** argv) {
Factory factory;
Animal* animal = factory.generateAnimal();
animal->get();
return 0;
}
The concrete implementation of an Animal class is resolved during runtime.
It's obvious, that removing the virtual keyword from Animal class results in calling Animal implementation of get() method, whether animal* points to Bird or Chicken.
What do you want? 1-Animal, 2-Bird, 3-Chicken
3
You chose Chicken
Animal is born
Bird is born
Chicken is born
get() from an Animal!
It's also obvious, that calling the virtual get() method results in polymorphic call to the concrete subclass.
What concerns me is this situation:
Instead of
Animal* animal = factory.generateAnimal();
animal->get();
we have
Bird* bird = factory.generateBird();
bird->get();
We have a pointer to Bird class, in which the get() method is NOT declared virtual. The output is:
What do you want? 1-Animal, 2-Bird, 3-Chicken
3
You chose Chicken
Animal is born
Bird is born
Chicken is born
get() from a Chicken!
How does it happen, that call to non-virtual function results in virtual call to the subclass?
Is "virtualism" inherited? If it is, is it somehow possible to perform a non-virtual call to the pointer class, instead of implementation class?
A virtual method remains virtual in inherited classes even if you don't specify the virtual keyword. Actually in C++11 you have a way to specify that method is overridden:
class Bird {
void get() override;
}
You can even specify the virtual keyword on overridden methods just to remember it yourself but you can't "remove" the dynamic dispatch of the method.
The only thing you are allowed to do is to choose the implementation by specifying it:
Bird *bird = new Bird();
bird->Animal::get();
We have a pointer to Bird class, in which the get() method is NOT virtual.
That's wrong. It is virtual. Virtual functions cannot be made non-virtual by derived classes. The virtual keyword is just optional there, but it has no effect.
In short, yes, virtual is "inherited". In other words, you can't "change it back" from virtual to non-virtual when you inherit from a base-class. That would make the system very fragile to typos (forget virtual, and all of a sudden you call a different member depending on which route you came to the object).
Say you have a class hierarchy
class A{
void f();
};
class B : public A{
void f();
};
class C : public B{
void f();
};
\\...
class O : public N{
void f();
};
class P : public O{
virtual void f();
};
class Q : public P{
virtual void f();
};
class R : public Q{
void f();
};
\\...
class Z : public Y{
void f();
};
As soon as, traversing the hierarchy, a member is declared to be virtual, it will be so for further derived classes too. In case you are wondering, there is no way for making Z::f() non-virtual if Q::f() is virtual.
What this mean is explained in this code:
Z z;
A& a = z;
O& o = z;
P& p = z;
Q& q = z;
Z& z = z;
a.f(); //calls A::f()
o.f(); //calls O::f()
p.f(); //calls Z::f()
q.f(); //calls Z::f()
z.f(); //calls Z::f()
z.A::f(); //calls A::f()
z.R::f(); //calls R::f()
of course this assumes that O::f() is overridden.
See also my answer to a related question.
Related
I created two objects from derived classes (Dog and Cat), which I assigned to one common array, which is the Animal type. Now I want to check a single element of the array to see if it is a dog. If there is, I want it to execute a method from Dog class and bark.
#include <iostream>
using namespace std;
class Animal{
public:
Animal() {}
virtual ~Animal() {}
};
class Dog : public Animal{
public:
Dog() {}
virtual ~Dog() {}
void soundOf(){
cout << "Woof woof" << endl;
}
};
class Cat : public Animal{
public:
Cat() {}
virtual ~Cat() {}
void soundOf(){
cout << "Meoow" << endl;
}
};
int main() {
Animal animals[2];
Dog dog;
Cat cat;
animals[0] = dog;
animals[1] = cat;
Animal *ptr = animals+0;
Dog* dg = dynamic_cast<Dog*>(ptr);
if(dynamic_cast<Dog*>(ptr) != nullptr){
cout << "This is a dog" << endl;
dg->soundOf();
}else if(dynamic_cast<Cat*>(ptr) != nullptr){
cout << "This is a cat" << endl;
dg->soundOf();
}
return 0;
In "if", I also used the following method
if(Dog* dg = dynamic_cast<Dog*>(ptr))
But the effect was the same. It returned NULL every time.
When I wrote the same application in Java, it was enough to use "instanceof", but here I can't do it.
Others have commented as to why you are having this issue but have not really suggested a fix. You should get into the habit of using dynamically allocated objects and ensuring they behave nicely by using std::shared_ptr and std::vector.
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
class Animal
{
public:
Animal() {}
virtual void soundOf() {}
virtual ~Animal() {}
};
class Dog : public Animal
{
public:
Dog() {}
virtual ~Dog() {}
void soundOf()
{
cout << "Woof woof" << endl;
}
};
class Cat : public Animal
{
public:
Cat() {}
virtual ~Cat() {}
void soundOf()
{
cout << "Meoow" << endl;
}
};
typedef std::shared_ptr<Animal> AnimalPtr;
int main()
{
std::vector<AnimalPtr> animals;
AnimalPtr dog = std::make_shared<Dog>();
AnimalPtr cat = std::make_shared<Cat>();
animals.push_back(dog);
animals.push_back(cat);
AnimalPtr ptr = animals[0];
if (dynamic_cast<Dog *>(ptr.get()) != nullptr)
{
cout << "This is a dog" << endl;
ptr->soundOf();
}
else if (dynamic_cast<Cat *>(ptr.get()) != nullptr)
{
cout << "This is a cat" << endl;
ptr->soundOf();
}
return 0;
}
this might seem long winded but will scale much better (and provides the functionality you want)
This question already has answers here:
Why do we need virtual functions in C++?
(27 answers)
Closed 6 years ago.
I've a question regarding inheritance
I've found this tutorial online, and was wondering why the output for "Dog" is actually "Animal print"
I understand that Animal pointer is pointing to the address of Dog,
but why isn't it printing "Dog print"?
Kindly help me out, I'm new to C++.
Below is the code:
#include <iostream>
using namespace std;
class Animal {
public:
void print();
};
void Animal::print() {
cout << "Animal print" << endl;
}
class Dog : public Animal {
public:
void print();
};
void Dog::print() {
cout << "Dog print" << endl;
}
int main() {
Dog h;
Animal *eptr = &h;
eptr->print();
eptr->Animal::print();
}
Output:
Animal print
Animal print
Here the child class object (dog) is pointed by a base class object (animal). But its limitation is only up to base class behavior.
#include <iostream>
using namespace std;
class Animal {
public:
virtual void print();
};
void Animal::print() {
cout << "Animal print" << endl;
}
class Dog : public Animal {
public:
void print();
};
void Dog::print() {
cout << "Dog print" << endl;
}
int main() {
Dog h;
Animal *eptr = &h;
eptr->print();
eptr->Animal::print();
}
You can use virtual function in order to access child class through base class object.
The following code gives me an error.
Error: overriding 'virtual void Animal::getClass()', where it says virtual void getClass() { cout << "I'm an animal" << endl; }
Error: conflicting return type specified for 'virtual int Dog::getClass()', where it says getClass(){ cout << "I'm a dog" << endl; }
Also, it says:
Class 'Dog' has virtual method 'getClass' but non-virtual destructor
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include<sstream>
#include <stdlib.h> // srand, rand
#include <stdio.h>
using namespace std;
class Animal{
public:
void getFamily(){ cout << "We are animals " << endl;}
virtual void getClass() { cout << "I'm an animal" << endl; }
};
class Dog : public Animal{
public:
getClass(){ cout << "I'm a dog" << endl; }
};
void whatClassAreYou(Animal *animal){
animal -> getClass();
}
int main(){
Animal *animal = new Animal;
Dog *dog = new Dog;
animal->getClass();
dog->getClass();
whatClassAreYou(animal);
whatClassAreYou(dog);
return 0;
}
Change the definition inside class Dog to:
void getClass() { /* ... */ }
When you declare it with no return type, the compiler sets the return type to int. This yields an error because the overriden method has to have the same return type as the base class method it overrides.
You are trying to declare function with no return type which was allowed in older version of C++. But the ISO C++ standard doesn't allow this (although some compilers may still allow, I guess like Codegear C++Builder 2007 that shows no error or warning at all). It has been mentioned in the standard - §7/7 footnote 78, and §7.1.5/2 footnote 80: implicit int banned.
Here is a reason why it was discarded:
void HypotheticalFunction(const Type);
In this function, what would be the argument type - const argument of type Type or argument of type const int with a name Type ?
Here is a better version of how you could define your class:
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include<sstream>
#include <stdlib.h> // srand, rand
#include <stdio.h>
using namespace std;
class Animal{
public:
void getFamily(){ cout << "We are animals " << endl;}
virtual void getClass() { cout << "I'm an animal" << endl; }
};
class Dog : public Animal{
public:
virtual void getClass(){ cout << "I'm a dog" << endl; }
};
void whatClassAreYou(Animal *animal){
animal -> getClass();
}
int main(){
Animal *animal = new Animal;
Dog *dog = new Dog;
animal->getClass(); // I'm an animal
dog->getClass(); // I'm a dog
Animal *animal1 = new Dog;
animal1->getClass(); // I'm a dog
whatClassAreYou(animal1); // I'm a dog
whatClassAreYou(animal); // I'm an animal
return 0;
}
§ C.1.6 Change: Banning implicit int In C++
a decl-specifier-seq must contain a type-specifier, unless it is followed by a declarator for a
constructor, a destructor, or a conversion function.
You are missing your type-specifier which is illegal in modern C++.
Use:
void getClass(){ cout << "I'm a dog" << endl; }
i'm trying to make specifics statements on the same class function's.
there's an example of what i'm triying to make
#include <stdio.h>
class animal
{
public:
void Talk();
};
int main()
{
animal dog;
animal cat;
dog::Talk()
{
printf("Wof");
};
cat::Talk()
{
printf("Meow");
};
dog.Talk();
cat.Talk();
return 0;
}
I also try it with class inheritance, something like
#include <stdio.h>
class cat
{
public:
void Talk()
{
printf("Meow");
};
};
class dog
{
public:
void Talk()
{
printf("Wof");
}
};
class animal{};
int main()
{
animal Schnauzer: public dog;
animal Siamese: public cat;
Schnauzer.Talk();
Siamese.Talk();
return 0;
}
There's a way to do something like this?
It is a very basic thing to do in c++. You just have to know a little bit about inheritance. However, I am guessing that you are new to c++ and don't have much experience in using inheritance. So, I am giving you a simple solution using class inheritance below. Feel free to ask me if there is any confusion.
#include <iostream>
using namespace std;
class animal {
public:
virtual void Talk() {cout << "default animal talk" << endl;}
};
class dog: public animal {
public:
void Talk() {cout << "Wof" << endl;}
};
class cat: public animal {
public:
void Talk() {cout << "Meow" << endl;}
};
int main()
{
dog Schnauzer;
cat Siamese;
Schnauzer.Talk();
Siamese.Talk();
return 0;
}
I am having a weird problem, which I'm sure has an easy fix. I have a super class let's call it "Bird". Bird has a virtual function called chirp, which returns me 0. I also have a subclass lets call it...SomeOtherBird. SomeOtherBird is a subclass of Bird. The chirp() function for my subclass is supposed to return me 1.
So far:
Bird.Chirp() should return 0
SomeOtherBird.Chirp() should return 1
Some other bird is a subclass of bird.
Now assuming I pass in Bird into a seperate constructor, let's call it nest.
So: nest(Bird& x)
if I pass a SomeOtherBird in, and I call Chirp, it calls the virtual function of the main super-class and not of the subclass, so for example:
SomeOtherBird x;
Nest(x);
and then if I do x.chirp, the main method is called, not the one of the subclass.
How do I get the function in the sub-class to be called, and not the virtual main function?
Thanks
I worked for me.
ideone.com/RRfau
You really ought to include some example code with questions like this so we can help you.
#include <iostream>
#include <typeinfo>
class Bird
{
public:
virtual ~Bird() {}
virtual int chirp() { return 0; }
};
class SomeOtherBird : public Bird
{
public:
virtual int chirp() { return 1; }
};
void nest( Bird& x )
{
std::cout << typeid(x).name() << " says " << x.chirp() << '\n';
}
int main()
{
SomeOtherBird s;
nest( s );
Bird b;
nest( b );
}
Works fine as shown below. Perhaps you might not have made the base method virtual. Or there is something else wrong in the code, since the code was not posted, it is impossible to tell.
#include <iostream>
using namespace std;
class Bird
{
public:
Bird() {}
~Bird() {}
virtual int Chrip() { cout << "Bird version" << endl; return 0; }
};
class SomeOtherBird:public Bird
{
public:
SomeOtherBird() {}
~SomeOtherBird() {}
virtual int Chrip() { cout << "SomeOtherBird version" << endl; return 1; }
};
int nest(Bird &b)
{
b.Chrip();
}
int main()
{
SomeOtherBird s;
Bird &b = s;
int retcode = nest(b);
cout << "retcode " << retcode << endl;
}
Output:
rhdevblade1-~/cpp: ./virt
SomeOtherBird version
retcode 1
Without seeing your code it's impossible to answer you for sure. However, this sounds like you did not write "virtual Bird()" in your base class, only in the derived class. That doesn't work.
class Bird {
virtual int Bird();
};
class MoreBird : public Bird {
int Bird();
};
The virtual keyword is not required in the deriving class (although it is not good practice not to put it there even if 99.9% of the programmers are lazy and don't do it.)