Jeremy
Jeremy

Reputation: 399

How to prevent a derived class being an abstract class in c++?

I have a question about Polymorphism. The following example would result in a error of "cannot declare variable ‘obj’ to be of abstract type ‘B’"

I know that the problems lies in the pure virtual method of function A::foo(), which make A an abstract class. Furthermore, class B inherent from class A. If i didn't implement the method foo() in the body of B, does that necessarily make B an abstract as well? and hence causing the error? But what's the logic of this? There might be a lot other derived classes from my base class A, the function foo might be applicable in some derived class, but may be totally useless for Class B. Of course I can declare an empty function B::foo() which absolutely does nothing and make the code run. But, is there any better solution or explanation of this behavior? Thanks!

struct A
{
    A() : x(0)  {}
    virtual int foo() const = 0;   // if I remove this line, code will run with no problem.
    int x;
};

struct B :  A {};

int main()
{
    B obj;
    cout << obj.x << endl;

    return 0;
}

Upvotes: 1

Views: 1735

Answers (3)

Aconcagua
Aconcagua

Reputation: 25536

At first, you are right, not implementing foo in A makes A abstract, not implementing foo in B makes that one abstract as well.

The whole sense of polymorphism is that you provide a common interface for a set of classes. Any derived type can behave as a base type in general, the specific behaviour would deviate only in the details (e. g. like steering in a car, bike or ship, the mechanism is different, but you can steer all of them).

If it doesn't make sense to call foo on B, then first ask 'Why?'! Somehow, B cannot be a true A then, just like a screw driver cannot be a hammer (but both can be tools).

If you find yourself in such trouble, then most likely your design is flawed.

Upvotes: 5

JHBonarius
JHBonarius

Reputation: 11271

Class A is abstract because foo()=0. If you derive from A, you need to implement this foo(), else the derived class is still abstract.
So class B has to have

int foo() const override {}

To be able to be used as object

You could probably declare this function private, to not have it accessible... but the question is why B is derived from A if or doesn't implement foo(). Maybe you need to rethink your design.. maybe should move foo()=0 to a separate interface class, and implement multiple inheritance.

Class C : public A, public FooInterface {
public:
    int foo() const override {};
};

Alternatively you could implement an AwithFoo class that derives from A but adds foo(). I.e. add some hierarchy.

class A {}
class B : public A {}
class AwithFoo : public A {
public:
    using A::A; // a way to inherit the constructor.
    virtual int foo() const = 0;
}
class C : public AwithFoo {
public:
    int foo() const override {};
}

Although this latter solution is not always a good solution. It will add extra layers of indirection.

Upvotes: 3

Alexis Pavlidis
Alexis Pavlidis

Reputation: 1080

You shouldn't depend on classed that provide you with functionality that you don't need. If you do that you violate liskov substitution principle. That`s a bad design and will lead you to many problems such as refused bequest.

If however you need that functionality and inherit from a base class you have to either implement that function or leave it abstract which will make the derived class abstract as well.

Upvotes: 2

Related Questions