Reputation: 399
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
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
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
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