6

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?

Ajay
  • 18,086
  • 12
  • 59
  • 105
Mike James Johnson
  • 724
  • 2
  • 8
  • 29
  • *I was thinking my problem is because I specify the argument of AnotherClass as an object of class A* You are correct. You need to store a reference or pointer to `A` in the class. – NathanOliver Jun 09 '16 at 17:46
  • I've edited it, but not this: `B b();` - is your code even compiling? – Ajay Jun 09 '16 at 18:18

3 Answers3

7

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.

2

It will only work if it is a pointer A* a Look up on polymorphism. http://www.cplusplus.com/doc/tutorial/polymorphism/

if you wont to know more , read the article

kemis
  • 4,404
  • 6
  • 27
  • 40
2

You are slicing in your constructor to AnotherClass. Note you have a value of type A as a member. So the compiler is doing the right thing. You don't have a B at the point you call a.method().

Edward Strange
  • 40,307
  • 7
  • 73
  • 125