Inheritance - Output using pointer [duplicate] - c++

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.

Related

Polymorphysm Derived and Base class with :: Operator

The following programm creates a simple base class(Animal) and some derived classes(Frog,Cat).
The question occurs when typing Cat:: or Animal:: (See Code and you'llunderstand the question better)
#include <iostream>
using namespace std;
class Animal
{
protected:
int ID=4;
public:
void getID();
};
void Animal::getID()
{
cout << Animal::ID << endl;
}
class Frog:public Animal
{
public:
Frog();
};
Frog::Frog()
{
Animal::ID = 1;
}
class Cat:public Animal
{
public:
Cat();
};
Cat::Cat()
{
Cat::ID = 500;
}
int main()
{
Frog frog;
Cat cat;
cat.getID();
frog.getID();
}
/*
500
1
is printed to the screen
Question:
in line 26 whether I type Animal::ID=1;or Frog::ID=1;
I get the same result.
So in the derived class Frog, Animal:: and Frog:: are the same thing??
When I type Animal:: the programm understands Frog:: ??
(Same goes with Cat obviously)
*/
PS: Is there a way to cout the base(Animal) Class ID from a derived class(ex. Frog)??
(ex. frog.getID().SomeOtherFunction and the ID 4(Of the animal class is printed))

Is it possible to check the type of a derived class from an array element which is of the base type?

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)

C2084 - function already has a body

I'm running into an error "C2084 - function 'void Pet::display(void)' already has a body". Error occurs on Dog.cpp file. Slightly confused about the issue. Any help would be appreciated.
Pet.h
#ifndef _PET_H_
#define _PET_H_
#include <string>
using namespace std;
enum Type { dog = 0, cat };
class Pet {
private:
string name, breed; // private local variables
Type type;
public:
Pet(string pet_name, string pet_breed, Type pet_type); // constructor
// accessor methods
string getName();
string getBreed();
Type getType();
virtual void display() {};
};
#endif // _PET_H_
Dog.h
#ifndef _DOG_H_
#define _DOG_H_
#include "Pet.h"
#include <string>
using namespace std;
class Dog : public Pet {
public:
Dog(string pet_name, string pet_breed, Type pet_type) : Pet(pet_name, pet_breed, pet_type) {
} // constructor
virtual void display() = 0;
};
#endif
Dog.cpp
#include "Dog.h"
#include "Pet.h"
#include <iostream>
void Pet::display() {
cout << "Name: " << name << endl;
cout << "Breed: " << breed << endl;
cout << "Type: Dog" << endl;
}
It seems that you wanted to define Dog::display and have forgotten to rename Pet to Dog:
void Dog::display() {
cout << "Name: " << name << endl;
cout << "Breed: " << breed << endl;
cout << "Type: Dog" << endl;
}
Also remove " = 0" from:
virtual void display() = 0;
in "Dog.h".
In "Pet.h" file having " = 0" after function prototype is ok, it means that you shouldn't instantiate the Pet class directly (Abstract class).
In Pet.h you already have a body defined for display(), which does nothing.
In Pet.h:
class Pet {
/* other class members */
virtual void display() {}; // Here is your virtual function with an empty body.
};
In Dog.h:
class Dog : public Pet {
/* other class members */
virtual void display() = 0; // This pure virtual function which is inheriting from Pet which is not purely virtual.
};
Swap the two around.
Make Pet's virtual void display() = 0, i.e. a pure virtual function.
Make Pet's virtual void display(), i.e. a virtual function which you are already implementing in Dog.cpp.
Solution:
In Pet.h:
class Pet {
/* other class members */
virtual void display() = 0; // Make this a pure virtual function. It does not have an implementation.
};
In Dog.h:
class Dog : public Pet {
/* other class members */
virtual void display(); // This virtual function is implemented in Dog.cpp.
};
You are declaring the method display pure virtual in the class Dog which is derived from another class Pet. But the Pet class already has a concrete method called display. That' why you get this error.
Declare display as pure virtual in the Pet class and then give a concrete implementation in its child class Dog.

C++ - Function of a class with different statements

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;
}

Polymorphic call through non-virtual method

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.