Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Base class method being called instead of derived, even when passed by reference [duplicate]

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?

like image 638
Mike James Johnson Avatar asked Jun 09 '16 17:06

Mike James Johnson


People also ask

Why is the base class called when a derived class is created?

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.

What happens when a reference to a derived class object is assigned to a base class reference variable?

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.

Can we call derived class method from base class?

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.

What allows derived class to replace a method inherited from its base class?

Dynamic binding yields greater flexibility and is the underlying mechanism that allows a derived class to replace behavior inherited from a base class.


1 Answers

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.

like image 170
Martin Bonner supports Monica Avatar answered Sep 29 '22 12:09

Martin Bonner supports Monica