I have 3 classes: A
, B
, and AnotherClass
. Where B
is derived from A
:
class A {
public:
A(){}
virtual void method() {//default action}
};
Then I have a derived class, B:
class B : public A {
public:
B(){}
void method() {//redefine action}
};
And AnotherClass
:
class AnotherClass {
public:
AnotherClass(A& a);
A a;
anotherMethod(){ a.method()}
};
AnotherClass :: AnotherClass(A& a) : a(a) //initialization
So, if I construct an object of AnotherClass
with an object of B
:
B b();
AnotherClass myObj(b);
Keep in mind, since B
inherits from A
, and AnotherClass
accepts an object of A
, I am able to successfully pass in a B
object as the argument.
And I call:
myObj.anotherMethod();
I expect this to execute anotherMethod()
, and when it does, I expect it to call the REDEFINED method()
that belongs to B
, but instead it calls the default method()
defined in A
I was thinking my problem is because I specify the argument of AnotherClass
as an object of class A
. However, I do not want to change this argument to an object of class B
because I also have classes C
, D
, and E
, that also inherit directly from A
. So I want to use the base class as the argument type so I am not limited to only being able to pass in a b
object. But, I read some older posts on this site and most proposed solutions was to pass the derived object (b
) by reference, which I am doing.
Can someone explain why this is happening?
The class whose members are inherited is called the base class, and the class that inherits those members is called the derived class. A derived class can have only one direct base class. However, inheritance is transitive.
Moreover, Object slicing happens when a derived class object is assigned to a base class object, and additional attributes of a derived class object are sliced off to form the base class object.
Even though the derived class can't call it in the base class, the base class can call it which effectively calls down to the (appropriate) derived class. And that's what the Template Method pattern is all about.
Dynamic binding yields greater flexibility and is the underlying mechanism that allows a derived class to replace behavior inherited from a base class.
The argument to the constructor is fine. It is an object of type B
passed by reference to the A
subobject. The problem is that you copy the A
subobject only (and not the derived object) into the member variable a
. Then when you call a.method()
there is only a base object there, so the base function is called.
The solution is to make the member variable be a pointer or a reference (and not a copy) of the argument. (Note that in either case, you will then need to make sure that the object you pass in, will live at least as long as the AnotherClass
object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With