So i have the following code:
#include <iostream>
using namespace std;
class Parent
{
int x;
public:
Parent(){x=10;}
void f(){cout<<x;}
};
class Child: public Parent
{
int x;
public:
Child(){x=20;}
void f(){cout<<x;}
};
int main()
{
Parent *pp;
Child c;
pp=&c;
pp->f();
return 0;
}
As you can see, i have two classes, Parent class and Child class publicly inherited from Parent class, so i wanted to see what can i do with pointer to a parent class.
I thought that it would be possible to use pointer to the parent class and use it on a child object, as i did in main, however, whenever i run this code, it prints out 10, which is the value i have for parent class variable x, considering that i made pp to point to child object, shouldn't it call the function f() defined in the child class and therefore, it should print the value of 20. What am i missing here? Any help appreciated!
The method f has to be virtual. As a start read this reference maybe helps.
#include <iostream>
using namespace std;
class Parent
{
int x;
public:
Parent(){x=10;}
virtual void f(){cout<<x;}
// ^^^^^^^ see this
};
class Child: public Parent
{
int x;
public:
Child(){x=20;}
virtual void f(){cout<<x;}
// ^^^^^^^ and this
// or since C++11 with override:
// void f() override {cout<<x;}
};
int main()
{
Parent *pp;
Child c;
pp=&c;
pp->f();
return 0;
}
Demo
There are at least two problems in the code.
First, the function f() must be declared virtual at least in the Parent class (with C++11 and later it is then good practice to append the keyword override in the Child class). The function being virtual is the mechanism that makes it possible to call the Child implementation via a Parent pointer.
Second, the variable x is declared both in the Parent and the Child class. This means that the Child object has two variables called x and by default x in Child functions will refer to the x declared in the Child class (the copy in the Parent class must be public or protected to be accessible from Child and must then, because of the name overlap, be referred to via a Parent type pointer or by explicitly specifying the class as in Parent::x).
Related
I have one base class and two derived child's (different classes).
I would like to construct one child and then construct a second child which uses the same base class instance like the first child.
In pseudo code this would look like this:
class Parent
{
public:
int x;
};
class ChildA : public Parent
{
void setX() {x=5;}
};
class ChildB : public Parent
{
int getX() {return x;} //Shall return 5 after calling the set method of ChildA first
};
//Creating instances
ChildA* a;
a = new ChildA();
Parent* ptrToBaseClass = a;
ChildB* b;
b = new ChildB(); //How can I set this to the same base class ptr (Parent*) which instance “a” has?
How can this be achieved with passing the base class pointer?
I would like to construct one child and then construct a second child which uses the same base class instance like the first child.
What you would like is not possible. Each base class sub object is stored within the most derived object.
You can use the existing base to copy initialise the base of another object, but they will be separate.
What you could do to achieve something similar, is to use indirection:
struct Parent
{
std::shared_ptr<int> x = std::make_shared<int>();
};
struct ChildA : Parent
{
void setX() {*x=5;}
};
struct ChildB : Parent
{
int getX() {return *x;} //Shall return 5 after calling the set method of ChildA first
};
int main() {
ChildA a;
Parent& a_base = a;
ChildB b {a_base}; // note that the base is copied here
a.setX();
std::cout << b.getX();
}
This way even though the base objects are separate, they both refer to shared state.
A simpler solution is to store the state in static storage (such as static member, as suggested by Ahmet). But this will make the state shared across all instances while the indirection allows exact control over which objects share which state.
You can make the x in Parent class static. This will allow you to do this - although I have to warn you that this is quite a dodgy code and can bite you in the a**.
Of course, then you have to access it with rather than just x; as Parent::x.
EDIT: I seem to got it wrong. If you want the whole base class as 'shared' rather than just x; you need pointers and custom logic to manage it - there is no direct language construct.
Assume the following:
class child : public parent
{
public:
fun1(parent * obj);
//somewhere on the child class:
fun2 ()
{
fun1(this::...POINTER TO THE PARENT....); //how can I do such a thing without having to create an object of parent class?
}
};
I am looking for something similar to 'this' pointer that points at the address of the current class. But, is there a "this" kinda thing for referencing a parent class inside a child's class?
The parent is the base class not the derived class. Also this is implicitly convertible to the base class type, so you could just pass it around.
In your case:
class child : public parent
{
public:
fun1(parent * obj);
//somewhere on the child class:
fun2 ()
{
fun1(this);
}
};
And finally, in the specific case you are showing, what you are trying to do doesn't make any sense. The child can access directly to any protected or public member of the base class, so you don't need to pass a pointer to the parent.
Like the following:
class parent
{
/* Rest of the code here */
protected:
int m_member;
};
class child : public parent
{
public:
int fun1() { m_member = 1; }
};
I'm working with some production code, some of which I cannot safely modify (without breaking things). My issue is that it I would like to use a specific method, one of the parameters of which is a pointer to a class. However the class as the parameter does not do what I want it to.
So I wrote a sub-class of that class and am attempting to call the above function, but it still uses the parent class' methods.
I have a MWE below:
#include <iostream>
class Parent
{
public:
Parent() {};
void method() {std::cout<<"in Parent\n";}
};
class Child : public Parent
{
public:
Child() {};
void method() {std::cout<<"in Child\n";}
};
void secondMethod(Parent* Pptr)
{
Pptr->method();
}
int main()
{
Child c = Child();
Parent* parentPtr = &c;
c.method();
parentPtr->method();
secondMethod(parentPtr);
secondMethod(&c);
return 0;
}
In the above example running this the output is of course:
in Child
in Parent
in Parent
in Parent
I believe the issue is slicing? Basically I'm casting to the pointer of the parent class, so it is considered as a Parent.
I have seen some ways around this by making methods virtual in the parent class but I don't have that option.
Is there some way to make secondMethod actual use the child's method? Specifically without changing the Parent class OR the secondMethod.
No not really if you aren't able to change the parent class or 'secondMethod'. The constructor of 'secondMethod' defines its parameter as Parent*. Passing a Child* to 'secondMethod' will cause the Child* to be upcast to Parent* and in turn will cause Parent's implementation of 'method' to be called.
If you can not change method to virtual function, you may can import template to solve your problem.
template<typename T>
void secondMethod(T* Pptr)
{
Pptr->method();
}
it may can work!!!
Say we have two classes:
class Parent
{
public:
vector<int> x;
protected:
void Method();
}
and
class Child : public Parent
{
public:
vector<double> x;
}
and the method Method() operates on x and makes some operation, which is compatible for both types int and double:
void Parent::Method()
{
x.push_back(1);
}
Then, if I will create an instance of Child class, initialize vector<double> x, and then call derived method Method() from the base class, C++ will try to operate on Parent's member x and not the Child's one. Is there any way how to make base class method to automatically operate on the member that belongs to created class, Child's vector<int> x?
EDIT:
As McAden correctly noted, this behavior can be easily achieved using polymorphism: three classes - 1 base and 2 derived. But does it mean that it is impossible with just 2 classes?
Since you only want to create instances of Child and you want the Child to dictate the type of the vector, this problem is more naturally solved with a template Parent. As a simple example, Parent could be parameterized by what vector<> should contain:
template <typename T>
class Parent {
public:
std::vector<T> x;
protected:
void Method () { x.push_back(1); }
};
class Child : public Parent<double> {
//...
};
If you actually have many such things you want the child to control in the Parent, then you probably should treat Child more like a traits class for the Parent. Thus, Parent would actually be parameterized by its Child, and your code would then be using CRTP. which provides "static polymorphism".
template <typename CHILD>
class Parent {
protected:
void Method () {
CHILD *child = static_cast<CHILD *>(this);
child->x.push_back(1);
}
};
class Child : public Parent<Child> {
public:
std::vector<double> x;
};
Changing data types in dealing with inheritance isn't so much possible with the exception being cases where covariance is used. If you want to make a class that handles differing data types what you're probably looking for is a template class:
http://www.learncpp.com/cpp-tutorial/143-template-classes/
#include<stdio.h>
class parent
{
public:
parent()
{
}
};
class child : public parent
{
public:
child()
{
}
};
class master
{
public:
void view(parent a)
{
printf("view parent instances");
}
void view(child b)
{
printf("view child instances");
}
};
int main()
{
parent *ptr;
master mymaster;
ptr = new child;
mymaster.view(*ptr);
return 0;
}
output : "view parent instances"
I create a pointer from parent class. then I declared that pointer as child type. when i run mymaster.view(*ptr); , this always go to first view function (void view(parent a)), how to make it go to (void view(child b)). thankyou
With a little refactoring and a slightly different approach, you could use virtual functions. This enables the function from derived classes to be used when called using a pointer like below.
#include<stdio.h>
class parent
{
public:
parent()
{
}
virtual void view()
{
printf("View parent");
}
};
class child : public parent
{
public:
child()
{
}
virtual void view()
{
printf("View child");
}
};
class master
{
public:
void view(parent *a)
{
a->view();
}
};
int main()
{
parent *ptr;
master mymaster;
ptr = new child;
mymaster.view(ptr);
return 0;
}
This will output "View child". The same code without the virtual keywords will output "View parent". Note that the keyword only needs to be in the parent class, but is often used in the derived classes too for clarity.
The Wikipedia article on virtual functions explains the situation pretty well:
Virtual functions are resolved 'late'. If the function in question is
'virtual' in the base class, the most-derived class's implementation
of the function is called according to the actual type of the object
referred to, regardless of the declared type of the pointer or
reference. If it is not 'virtual', the method is resolved 'early' and
the function called is selected according to the declared type of the
pointer or reference.
Since the actual type of the object here is a child, the virtual function makes sure that the child's functionality is called even though the pointer is of parent type.
The type of *(parent*) is parent, so the method that gets called is view(parent). If you want to invoke view(child), you need to cast the pointer to a child* before passing it in, however...
You're using OOP backwards. You don't define multiple methods that know how to consume each specific type of sub-class, you define one method that can respect the contract provided by the parent class, and the sub-classes do their own thing internally.
ptr is a pointer to a parent object.
If you want to have the view(child) function called, you need to pass a child object to the function call.
Alternatively, you can cast it to a child pointer
mymaster.view(*(child*)ptr);
but you're likely to end up with all kinds of other problems.
The compiler decides the matching method according to the best choice.
The compiler sees that the variable is of type parent, so it calls the matching method.