Implementing a pure virtual function by inheriting it from a base class

Started by
3 comments, last by aclysma 12 years, 11 months ago
I'm writing a library that is exposed as a DLL, so I am using the standard pImpl method with exposed factory functions to create the Impl objects. I'd like for some of the common "Impl" functionality to be in a base class, and have those implementation satisfy the exposed interface. So, I have some code that's like this:

struct InterfaceA
{
virtual void fn() = 0;
};

class ClassA
{
public:
void fn() { }
};

class ClassB :
public ClassA,
public InterfaceA
{

};


I expected that this would work, however, I get the following:

1>****(38) : error C2259: 'ClassB' : cannot instantiate abstract class
1> due to following members:
1> 'void InterfaceA::fn(void)' : is abstract
1> ****(19) : see declaration of 'InterfaceA::fn'


I know that I could include something in class B like

void fn() { ClassA::fn(); }

but at that point I might as well just use composition rather than inheritance. While in general I'm a huge fan of composition, I wanted to use inheritance so that the "ClassB" classes have only the unique code in them (would make the code pleasant to read.) Is there a way to make ClassB automatically use the method in ClassA to satisfy InterfaceA?

My question is exactly the same as http://stackoverflow...-abstract-inter, but I didn't see a real "solution" to my question of not having to add a proxy function. Also, if there is a good reason why this is not possible for a compiler to figure out, or why you wouldn't want this behavior, I'd love to know.
Advertisement
Why don't you make ClassA inherit from InterfaceA, since it does implement that interface? Then ClassB could just inherit only from ClassA.
Is there a reason why ClassA cannot inherit from InterfaceA?
Thanks for your suggestion alvaro. I think I stripped down my sample source too much, so here's a version that's a bit closer to what I'm actually doing:



struct InterfaceA
{
virtual void fn() = 0;
virtual void fnA() = 0;
};

struct InterfaceB
{
virtual void fn() = 0;
virtual void fnB() = 0;
};

class BaseClass
{
public:
void fn() { }
};

class ClassA :
public BaseClass,
public InterfaceA
{
void fnA() { }
};

class ClassB :
public BaseClass,
public InterfaceB
{
void fnB() { }
};



While your suggestion certainly works well for my original post, it does not work for this case. The above code will complain that ClassA and ClassB do not have an implementation for fn(). If I make the base class extend both interfaces, ClassA will complain about missing fnB() and ClassB will complain about missing fnA().

Using your idea, I did come up with this. While it's a bit weird, it does remove the need for the proxy functions, and it gives compile-time errors because the dummy functions in BaseClass are private.

struct InterfaceA
{
virtual void fn() = 0;
virtual void fnA() = 0;
};

struct InterfaceB
{
virtual void fn() = 0;
virtual void fnB() = 0;
};

class BaseClass :
public InterfaceA,
public InterfaceB
{
public:
void fn() { }

private:
// Dummy methods that should always be extended.. we get compile errors
// if we try to call them because they are private
void fnA() { assert(0); }
void fnB() { assert(0); }
};

class ClassA :
public BaseClass
{
public:
void fnA() { }
};

class ClassB :
public BaseClass
{
public:
void fnB() { }
};


Far from elegant, and I'm not really sure that it's better than having proxy functions.

I am still interested in:
- Solutions that are not a hack like this one that uses visibility
- An explanation as to why a compiler couldn't or shouldn't do what I expected with the very original code sample
In that particular case InterfaceA::fn() and InterfaceB::fn() are two different functions. If you create a BaseInterface with a virtual function fn() and let both InterfaceA and InterfaceB inherit from it, then you can share the implementation using virtual inheritance.
http://en.wikipedia.org/wiki/Virtual_inheritance
http://www.parashift.com/c++-faq-lite/multiple-inheritance.html
Thank you both for your help! In particular, the explanation of *why* ClassA and ClassB don't implement InterfaceA::fn() or InterfaceB::fn(). I haven't finished what I'm working on, but I fully expect that making a "shared" interface is the right answer.

This topic is closed to new replies.

Advertisement