0

In implementations of pure virtual classe (B_Impl below) do we need to define all methods corresponding to all derived pure virtual classes (A and B) even if we are also deriving from implementation classes (A_Impl). I have following pure virtual classes:

class A
{
public:
virtual bool M1() = 0;
virtual ~A() = default;
};

class A_Impl: public virtual A
{
public:
bool M1() override { return true;}
virtual ~A_Impl() = default;
};

class B : public virtual A
{
public:
virtual ~B()=default;
virtual bool M2() = 0;
};

class B_Impl : public B, public A_Impl
{
public:
virtual ~B_Impl() = default;
bool M2() override { return true; }
};

int main()
{
    B_Impl bimpl();
    return 0;
}

On compiling this I am getting following error:

1.cpp: In function ‘int main()’: 1.cpp:31:5: error: invalid abstract return type ‘B_Impl’ B_Impl bimpl(); ^~~~~~ 1.cpp:22:7: note: because the following virtual functions are pure within ‘B_Impl’: class B_Impl : public B, public A_Impl ^~~~~~ 1.cpp:4:14: note: virtual bool A::M1() virtual bool M1() = 0;

I dont want to define all methods of A in B_Impl as well when I am deriving from A_Impl also.

2 Answers2

0

Your code lacks of multiple problems.

First A_Impl does not derive from A, which means, that it cannot override M1.

I think your approach is not elaborate very well and you should consider rethink your architecture.

hellow
  • 12,430
  • 7
  • 56
  • 79
-1

Your problem here is that a B_Impl object has two A subobjects, one of which does not have its M1 method overridden.

A B_Impl object looks something like this:

+-------------------------+
| +---------+ +---------+ |
| | +-----+ | | +-----+ | |
| | |     | | | |     | | |
| | |  A  | | | |  A  | | |
| | |     | | | |     | | |
| | +-----+ | | +-----+ | |
| |  A_Impl | |  B      | |
| +---------+ +---------+ |
|         B_Impl          |
+-------------------------+

It has A_Impl and B subojtects, each of which has its own A subobject.

To fix this, you need to use virtual inheritance. If you declare A_Impl and B to inherit virtually from A, then B_Impl will end up looking like this:

+--------------------------+
| +-----+ +------+ +-----+ |
| |     | |      | |     | |
| |  A  | |A_Impl| |  B  | |
| |     | |      | |     | |
| +-----+ +------+ +-----+ |
|          B_Impl          |
+--------------------------+

It has one A subojbect that is shared by B and A_Impl.

To do that, just add the virtual keyword:

class A                               
{                                        
public:
    virtual bool M1() = 0;
    virtual ~A() = default;
};

class A_Impl : public virtual A
{
public:
    bool M1() override { return true;}
    virtual ~A_Impl() = default;
};

class B : public virtual A
{
public:
    virtual bool M2() = 0;
    virtual ~B()=default;
};

class B_Impl : public virtual B, public A_Impl
{
public:
    virtual ~B_Impl() = default;
    bool M2() override { return true; }
};

Note that I've also declared B_Impl to derive virtually from B. In general, it's a good idea to inherit virtually from interfaces. That way you won't end up with the same problem if you mix in a C interface that derives from B and a C_Impl that derives from C and B_Impl.

Just keep in mind that it's the most-derived class's job to initialize any virtually-derived-from classes, so if you were to make A non-default-constructable then it would end up being the responsibility of B_Impl to call A's constructor rather than that responsibility being hidden by A_Impl.

Miles Budnek
  • 28,216
  • 2
  • 35
  • 52