using pointers with inheritance in C++ - c++

I have a problem in understanding one important aspect of the c++. see the example below:
class human
{
protected:
int age;
public:
human(int a){age=a;}
void f(){cout<<"\n the age of human ="<<age;}
};
and the class below is derived from above class:
class student: public human
{
private:
int num;
public:
student(int b, int c):human(b){num=c;}
void g(){cout<<"\n the student with age "<<age<<" has " <<num;}
};
now I want to use these classes in the code below:
int main()
{
human h1(10);
student s1(11,4);
human* p=&h1;
p->f();
p=&s1;
p->g();
}
but the compiler gives me error on the p->g().
what is the problem?

Your base class pointer still points to a base class object human* p=&h1;. Try something like this:
#include <iostream>
class human
{
protected:
int age;
public:
human(int a){ age = a; }
void f(){ std::cout << "\n the age of human =" << age; }
virtual void g(){}
};
// class student code here...
int main()
{
human* p = new student(11, 4);
p->f();
p->g();
delete p;
return 0;
}
or instead use the s1 object and not the h1:
student s1(11, 4);
human* p = &s1;

The function g() is not part of the interface of the class human. p is a human*. If you upcast p to a student*, it will work.

The compiler doesn't know that your pointer is of student, it only sees the declaration as human. To fix this you need to cast it to a student pointer.
((student*)p)->g();

You can announce a virtual g in the Human.
class human {
public:
virtual void g() {}
... ...
};

In your example main() has two objects: human h1 and student s1.
int main()
{
human h1(10);
student s1(11,4);
human* p=&h1;
p->f();
p=&s1;
p->g();
}
Aside from the constructor, the declaration of the parent class human has only the function f() and the child class student, only adds the one function g().
The human pointer can look up only the function contained in it's class. Any information in the child's look up table is unknown to the parent because human was never told anything about the child class.
Passing the child object's reference &s1 to the parent pointer means that the parent can only look up the function it already knows. This is sometimes called object slicing. The child function g() has no place keeper in the parent's class. But, the child has both functions in it's look up table.
In other words, the child knows both itself and it's parent because it is declared class student: public human but the parent class knows only itself because it is merely declared "class human"
As Bauss says, it is possible to "upcast" the human pointer but I would not recommended that style. It will only confuse what type of pointer is being actually used.
This is the way I would rewrite main:
int main()
{
human h1(10);
human* p=&h1;
p->f();
/* prints " the age of human = 10" */
student s1(11,4);
student* q=&s1;
q->f();
/* prints " the age of human = 11" */
q->g();
/* prints " the student with age 10 has 4" */
}

Related

How to create objects that has a variable based on the data from another object that is passed in the constructor

The title may be a little confusing but hear me out. I have this two classes , Entity and Human.
Entity is the parent class of human. When I create a human object, it will require an Entity object passed as argument in the constructor so all the human objects that I create has the same Entity object info.
This is my problem: If I change some data from the Entity object I want to update all the data from the Human objects that I created using that Entity Object in the constructor.
I want to implement this in ones of my University projects so I am allowed to use only the standard library.
I wrote this example so it's easier to understand:
#include <iostream>
using namespace std;
class Entity{
private:
//DATA
int life;
public:
//DEFAULT CONSTRUCTOR
Entity() {life = 100;}
//PARAMETRIZED CONSTRUCTOR
Entity(int life) {this -> life = life;}
//GETTER
int get_life(){return life;}
//SETTER
void set_life(int new_life){life = new_life;}
//FUNCTIONS
void print_life() {cout << "This entity has " << life << " life" << endl;}
};
class Human : public Entity{
public:
//DATA
string name;
//DEFAULT CONSTRUCTOR
Human() {name = "N/A";}
//PARAMETRIZED CONSTRUCTOR
Human(string name, Entity object){
Entity::set_life(object.get_life());
this -> name = name;
}
};
int main(){
//DATA
Entity Human_data(50);
Human Hero("Steve", Human_data);
Human Villain("Mike", Human_data);
//BODY
Human_data.set_life(5000);
Hero.print_life();
//END MAIN
return 0;}
As you can see, after I update Human data life from 50 to 5000, it does not also change Hero and Villain life to 5000 and only changes Human data life to 5000.
I'm assuming that when you call Human_data.set_life(5000) you want to effect all Human objects constructed with the Human_data object.
Here's an example of how you might use references for that. But note putting a reference inside a class is not without consequences. You might use a pointer instead, or even better a smart pointer. But I'm just trying to indicate the general idea.
On a technical note, using references means you have to get used to using initializer lists since references cannot be assigned.
#include <iostream>
using namespace std;
class Entity{
private:
int life;
public:
Entity() : life(100) {}
Entity(int life) : life(life) {}
int get_life() {return life;}
void set_life(int new_life){life = new_life;}
void print_life() {cout << "This entity has " << life << " life" << endl;}
};
class Human { // no inheritence
private:
Entity& entity; // store a reference to the entity
public:
string name;
Human(string name, Entity& object) // object is a reference
: entity(object), name(name)
{
}
void print_life() { entity.print_life(); } // forward to entity
};
int main(){
//DATA
Entity Human_data(50);
Human Hero("Steve", Human_data);
Human Villain("Mike", Human_data);
//BODY
Human_data.set_life(5000);
Hero.print_life();
//END MAIN
return 0;
}
The inheritance could be correct, if all "humans" are also entities (remember that inheritance is an "is a" relationship).
But the implementation is flawed.
Instead of passing an Entity object to the Human constructor, and using the separate and distinct Entity object to control the "life", pass the life itself to the Human constructor, and use set_life on the Human object directly.
Something like this:
class Human : public Entity
{
public:
// By default humans start out with 50 in life
Human(std::string const& name, int life = 50)
: Entity(life), name(name) // Initialize the parent class, then the name
{
}
private:
std::string name;
};
int main()
{
Human hero("The Hero", 5000); // The hero will have 5000 life
Human villain("The Villain"); // The villain will only have 50 life
// Some stuff...
// Update the heroes life
hero.set_life(4000); // Uh oh, the hero have lost 1000 life!
// ...
}

Acessing subclass variable from base class object

Let's say i'm having the following classes in c++
class Animal{}
class Dog : public Animal {
int barkingVolume;
}
However, i don't have the header file for Dog class. But i have the object of Dog of type Animal at runtime.
The question is how I can access the variable barkingVolume?
Animal animalButDogObject;//someone has set the value at runtime
I need to access barkingVolume from animalButDogObject.
Actual scenario from COM/Directshow: I'm having IBaseFilter object which is of type IVendorFilter(custom filter from 3rd party vendor which extended IBaseFilter). While debugging using Visual studio i can see the type is IVendorFilter and it has variables which i need to change. However i cannot figure out how to do it. I cannot find anything like a reflection/evalutation in CPP
I'd rather comment than post an answer, but can't due to lack of reputation, so here we go.
This is pretty bad, but if you know the exact layout of the class you must access, you could just forward declare the whole thing and reinterpret_cast the object you need.
// FooBar.cpp or something
namespace FooBar
{
class Foo {};
class Bar : public Foo
{
public:
Bar(int ival, float fval) : ival(ival), fval(fval) {}
int ival = 0;
float fval = 0.0f;
};
}
// OtherFile.cpp
class ForwardDeclaredBar
{
public:
int ival;
float fval;
};
#include <iostream>
int main()
{
FooBar::Foo* foo = new FooBar::Bar(3, 2.7f);
auto bar = reinterpret_cast<ForwardDeclaredBar*>(foo);
std::cout << "ival = " << bar->ival << ", fval = " << bar->fval << std::endl; // shows expected values
return 0;
}
Again, this is pretty bad since any changes to the "real" class will mess up your result (reinterpret_cast will just shove whatever data it finds into the format you specified).
There are probably many other reasons which I've no idea about. I'm also unsure how well (if at all) this plays with more complex objects.
declare method on Animal (base) class and overwrite it on Dog (derived) class.
// Base class
class Animal
{
public:
virtual int getBarkingVolume() = 0;
};
// Derived class
class Dog : public Animal
{
private:
int barkingVolume = 8;
public:
int getBarkingVolume()
{
return barkingVolume;
}
};
In main method has Animal (base) type and each derived class that implements the appropriate method (getBarkingVolume) will be compatible with that type.
int main()
{
Animal* animal = new Dog();
std::cout<<"barking: "<< animal->getBarkingVolume();
}

C++ array of the same class hierarchy

According to my book, if I want to make an array of objects that are not in the same class but in the same class hierarchy, I need to use pointers:
class text
{
public:
void write(string text);
void show();
private:
string texte;
};
void text::write(string text)
{
texte = text;
}
void text::show()
{
cout << texte;
}
class text_with_stars : public text
{
public:
void show();
};
void text_with_stars::show()
{
cout << "*";
text::show();
cout << "*";
}
int main()
{
text* array[2];
array[0] = new text;
array[0]->write("Hello");
text_with_stars* pointer = new text_with_stars;
pointer->write("Hi");
array[1] = pointer;
for (int i=0;i<2;i++)
{
array[i]->show();
}
return 0;
}
But when I do this, the output is "HelloHi" meaning that the second object used the show version that is from text and not from text_with_stars, but I made it exactly the same way that the book described. What Is the problem??
Here is what is written in the book:
Question* quiz[2];
quiz[0] = new Question;
quiz[0]->set_text("Who was the inventor of C++?");
quiz[0]->set_answer("Bjarne Stroustrup");
ChoiceQuestion* cq_pointer = new ChoiceQuestion;
cq_pointer->set_text("In which country was the inventor of C++ born?")
cq_pointer->add_choice("Australia",false);
...
quiz[1] = cq_pointer;
The chapter right next to the one I was reading is about virtual functions and it explains that the system will always use the member functions of Question instead of ChoiceQuestion, looks like I should read more before asking questions on internet!
void show()
needs to be virtual in the base class if you want to use methods from derived classes from base class pointers
The reason this is happening is because the function you are calling is non-virtual.
Let's say we have a class Parent and a class Child inheriting from the parent:
class Parent {
public:
void f() {
cout << "Parent::f()" << endl;
}
};
class Child : public Parent {
public:
void f() {
cout << "Child::f()" << endl;
}
};
Now, let's make a pointer to a Parent and store a Child in it (polymorphism):
Parent *ptr = new Child;
ptr->f();
At this point, the compiler sees ptr having type Parent* and determines that the function to be called is Parent::f().
In order to call Child::f() when dealing with polymorphism? The Parent::f() must be defined virtual. The compiler then generates code to check at run-time the value that is stored in memory to call the appropriate (child) function.
In short: ONLY when a function is virtual and is called on a pointer or reference, a memory lookup is made to determine the actual type at that point in memory. Otherwise it is not.

Memory sharing; Inheritance; Base and Derived instances; C++

Ok, this example is pretty straight-forward for the concept I'm trying to understand. I'll just show you the code:
class Base
{
protected:
string name;
public:
virtual string getName() const { return this->name; }
virtual void setName(string name) { this->name = name; }
....
}
class Derived : public Base
{
private:
double price;
....
}
main(int argc, char** argv)
{
Base* base = new Base("Base Class");
Derived* derived = new Derived(base, 453.21);
derived->setName("Name changed!");
cout << "Name of instance: " << base->getName() << endl;
// Desired effect
Output: 'Name changed!'
// Actual effect
Output: 'Base Class'
....
}
The issue for me is this. I want to create an instance of derived class with reference to already created instance of base class, so when I change any member variable of base class trough the derived instance, I can see the change on previously created base instance in the way demonstrated above.
Note: I hope that you will manage to comprehend what I meant, as I am aware that my terminology is probably little off. Please, don't be harsh. :)
Note: I won't be showing / writing constructors, since I am not sure what is the best way to do this, if even any exists and the syntax may be incorrect.
This seems to indicate the problem:
Base* base = new Base("Base Class");
Derived* derived = new Derived(base, 453.21);
as it is usually not necessary to construct the Base class separatly. Your derived class will already contain a Base instance implicitly, you don't have to add a pointer to one manually and set it from the ctor. I don't know how your ctor looks, but it should look like this:
Derived(const std::string& name, double p) : Base(name), price( p ) {}
If this enough to fix it yourself, good, otherwise post all the code of your example. Instead of the two lines from your code that I quoted above, it should look more like:
Derived* derived = new Derived("Base Class", 453.21);
If you post the code of Derived, it should be obvious for us and it will be much easier to explain it to you on your concrete example.
The way you are trying to do is weird, but you can simply use inheritance concept like this code:
class Base
{
public:
Base(const string &name) : name(name) {}
virtual void setName(const string &name) { this->name = name; }
virtual string getName() const { return name; }
protected:
string name;
};
class Derived : public Base
{
public:
Derived(const string &name, double price) : Base(name), price(price) {}
private:
double price;
};
int main()
{
Derived* derived = new Derived("Base Class", 453.21);
derived->setName("Name changed!");
Base *base = derived;
cout << "Name of instance: " << base->getName() << endl;
}
Output
Name of instance: Name changed!
You don't need a create Base object and pass it to the derived object.
Instead, create a derived object and pass its address to a Base pointer.

C++ inheriting member functions of the same type signature (shadowing)

// Shadowing
#include <iostream>
using namespace std;
const int MNAME = 30;
const int M = 13;
class Person { // Base Class
char person[MNAME+1];
public:
void set(const char* n);
void display(ostream&) const;
protected:
const char* name() const;
};
void Person::set(const char* n) {
strncpy(person, n, MNAME);
person[MNAME] = '\0';
}
void Person::display(ostream& os) const {
os << person << ' ';
}
const char* Person::name() const { return person; }
class Student : public Person { // Derived
int no;
char grade[M+1];
public:
Student();
Student(int, const char*);
void display(ostream&) const;
};
Student::Student() {
no = 0;
grade[0] = '\0';
}
Student::Student(int n, const char* g) {
// see p.61 for validation logic
no = n;
strcpy(grade, g);
}
void Student::display(ostream& os) const {
os << name() << ' '
<< no << << ' ' << grade << endl;
}
int main() {
Person person;
Student student(975, "ABBAD");
student.set("Harry");
student.display(cout); // Harry 975 ABBAD
person.set("Jane Doe");
person.display(cout); // Jane Doe
}
The first call to display() (on student) calls the Student version of
display(). The second call to display() (on person) calls the Person
version of display(). The derived version of display() shadows the
base version on the student object. The base version executes on the
person object.
I don't understand what shadowing is then. I realize that both classes have the same display function defined, and obviously if you call student.display and person.display its going to call them accordingly. So what does this mean:
The derived version of display() shadows the base version on the
student object. The base version executes on the person object.
I don't understand shadowing.
source: https://scs.senecac.on.ca/~btp200/pages/content/dfunc.html
Inheritance - Functions of a derived class
Your Student class inherits from Person. That means, among other things, that Student objects consist from all the internals defined in Student and from all the internals defined in Person - for this matter Student can be seen as containing the Person. This means that Student object contains both versions of display method - one from the the base class and one from the derived. Shadowing means that when invoking the display from the derived object, it will call the derived class version, and the base class version is "shadowed" by it and not called. You can call the shadowed version from within Student by explicitly specifying it with base class prefix: Person::display. In general, the function that will be called is the one closest in scope - for Derived objects it's the scope of Derived and functions residing in outer scopes (such as base) are shadowed away.
It means that you're most likely missing a virtual.
E.g., your Person class should probably look like:
class Person { // Base Class
char person[MNAME+1];
public:
void set(const char* n);
virtual void display(ostream&) const;
protected:
const char* name() const;
};
Right now, if you have the following code:
Person* student = new Student(975, "ABBAD")
student->set("Harry");
student->display(cout);
Your output will be "Harry " instead of "Harry 975 ABBAD\n". As icepack says, the reason you're getting the message is because the display method in the Student class "shadows" the display method in the Person class, and because you have not declared that method virtual, the compiler assumes that the shadowing is accidental. If it's not accidental, then you should declare that method virtual.
Try this little experiment. Define the following function:
void person_display(Person &p){
p.display(cout);
}
Then have main call it on person and student.
int main(){
// [...]
person_display(person);
person_display(student);
}
You will see that in both cases, the method Person::display will be called. The shadowing is a phenomenom happening because of the redefinition in a class of a method of its ancestor class. It shadows the previous definition, as long as the instance is considered as the subclass, but as soon as it is seen as the ancestor, the shadowing disappears.
This is in contrast with a virtual method, where the method called is always the one defined in the real instance class, ie. in the experiment described above, you would see the Student method being called, even though it is seen as a simple Person.