C++ and inheritance in abstract classes

2019-05-26 15:50发布

问题:

i have a problem in properly handling method overriding where an abstract class is present inside my classes hierarchy. I'll try to explain:

class AbstractClass{
public:
    virtual void anyMethod() = 0;
};

class A : public AbstractClass {
    void anyMethod() {
        // A implementation of anyMethod
        cout << "A";
    }
};

class B : public AbstractClass {
    void anyMethod() {
        // B implementation of anyMethod
        cout << "B";
    }
};

AbstractClass *ptrA, *ptrB;

ptrA = new A();
ptrB = new B();
ptrA->anyMethod();  //prints A
ptrB->anyMethod();  //prints B

Ok..previous example work fine .. the concrete implementation of the AbstractClass method anyMethod will be called at run time. But AbstractClass is derived from another base class which has a method not virtual called anyMethod:

class OtherClass {
public:
    void anyMethod() {
        cout << "OtherClass";
    }
};

class AbstractClass : public OtherClass {
public:
    virtual void anyMethod() = 0;
};

//A and B declared the same way as described before.

Now , if i try something like that:

ptrA = new A();
ptrB = new B();
ptrA->anyMethod();  //prints OtherClass
ptrB->anyMethod();  //prints OtherClass

What am I misunderstanding? Is there any solution for making ptrA and ptrB printing A and B without using cast, typeid, etc?

回答1:

Why don't you do:

class OtherClass 
{
    public:
    virtual void anyMethod()
    {
       cout << "OtherClass";
    };
}

That should solve your problems



回答2:

If anyMethod was declared virtual in the base class to which you have a pointer or reference, it should be looked up virtually and print A and B correctly. If it wasn't, then there is nothing you can do (beyond changing it to be virtual).



回答3:

I think that if the method in OtherClass that you want to override in A and B is NOT virtual, then the override is not implicit.

I believe there's a way to Explicitly override the functions, look that up.



回答4:

DeadMGs answer is of course correct. But, if you cannot change OtherClass Methode (e.g. it's from a third party lib) you might want to try this:

Are the pointers ptrA and ptrB of type OtherClass or AbstractClass in your lower example?

If they are OtherClass I would expect the behaviour you described. You could try casting the pointer to AbstractClass then:

dynamic_cast<AbstractClass*>(ptrA)->anyMethod();



回答5:

As far as I can see from your code OtherClass::anyMethod() is not a virtual and already implemented. It should work as you described if you define it as virtual



回答6:

I think that your declaration for the second case is: OtherClass* ptrA; and not AbstractClass *ptrA; if you declared like the first case , there's no problem because the method is virtual,but if you declare as OtherClass , the compiler will not find virtual and bind to the adress of this method without using vtble.



回答7:

thanks for the answers.. helped me a lot to understand the problem. In effect I posted some wrong code, because i was misunderstanding the real problem. Anyway, i think i partially solved my problem. Here's the code:

 #include <iostream>

``  using namespace std;

class Other{

public:

void foo(){
        cout << "Other\n";
}

void foo(int a){}
};

class Abstract : public Other{

public:
virtual void foo() {};
virtual void foo(int c){
        Other::foo(c);
}
};

class A : public Abstract{

public:

void foo(){
        cout << "A\n";
}
};

class B : public Abstract{

public:

void foo(){
        cout << "B\n";
}
};
int main(){

cout << "main\n";

Abstract * ptrA = new A();
Abstract * ptrB = new B();

Other *o = new Other();
o->foo();

ptrA->foo();
ptrB->foo();
ptrB->foo(3); //can't no more use the method foo with different signatures implemented in the base class Other, unless I explicitly redefined in the class Abstract
dynamic_cast<Other*>(ptrB)->foo(3);//can't dynamic_cast from derived to base

I was making two errors:

  1. In my real code (not the simplified version posted before) i forgot to declare virtual the function foo()

  2. Even declaring virtual wasn't enough. In fact all the implementations of that function must be wrapped inside the class Abstract to become visible to the subclasses A and b. Otherwise wont't compile.

I don't know if it could be a clean solution..in fact that way I need to wrap all foo method signatures.