I have two interfaces: IFace2 derives from IFace
class IFace
{
public:
virtual ~IFace() = default;
virtual void doit() = 0;
};
class IFace2 : public IFace
{
public:
virtual void doit2() = 0;
};
I am trying reduce code clutter that is required by the implementations. In IFace2Impl I would like to use the same implementation from IFaceImpl. Unfortunately, that forces me to resolve ambiguity and I need to override every function in IFace2Impl:
class IFaceImpl : public IFace
{
public:
void doit() override
{
}
};
class IFace2Impl : public IFaceImpl, IFace2
{
public:
using IFaceImpl::doit; // not resolving ambiguity
void doit2() override
{
}
};
int main()
{
IFace2Impl impl;
}
When I try to compile this code, the compiler gives me an error message:
<source>(36): error C2259: 'IFace2Impl': cannot instantiate abstract class
<source>(24): note: see declaration of 'IFace2Impl'
<source>(36): note: due to following members:
<source>(36): note: 'void IFace::doit(void)': is abstract
<source>(6): note: see declaration of 'IFace::doit'
https://godbolt.org/z/91M1j8bv3
For each virtual function I have to provide full definition:
class IFace2Impl : public IFaceImpl, IFace2
{
public:
void doit()
{
IFaceImpl::doit();
}
void doit2() override
{
}
};
Is there a way to handle this more elegantly? When number of interface method grows, the more ambiguities I have to resolve.
Virtual inheriance might help, so IFaceImpl would have only one IFace instead of 2:
class IFace
{
public:
virtual ~IFace() = default;
virtual void doit() = 0;
};
class IFace2 : public virtual IFace
{
public:
virtual void doit2() = 0;
};
class IFaceImpl : public virtual IFace
{
public:
void doit() override {}
};
class IFace2Impl :
public IFaceImpl,
public virtual IFace2 // virtual not required here, but would be with IFace3Impl...
{
public:
void doit2() override {}
};
Demo
Related
I have the following condition:
An absract base class with many pure virtual functions:
interface IBase
{
virtual void foo1() = 0;
virtual void foo2() = 0;
virtual void foo3() = 0;
virtual void foo4() = 0;
virtual void foo5() = 0;
// ...
virtual void fooN() = 0;
};
Two small interfaces that inherit it:
Version-A:
interface IBaseExt_A :
public IBase
{
virtual void foo_A() = 0;
};
Version-B:
interface IBaseExt_B :
public IBase
{
virtual void foo_B() = 0;
};
I create base class that implements all of the IBase interface functions:
class CBase :
public IBase
{
public:
virtual void foo1() { /* Do something... */}
virtual void foo2() { /* Do something... */}
virtual void foo3() { /* Do something... */}
virtual void foo4() { /* Do something... */}
virtual void foo5() { /* Do something... */}
// ...
virtual void fooN() { /* Do something... */}
};
Now, I want to implement both derived versions with minimal code.
I was hoping to do something like:
class CBaseExt_A :
public IBaseExt_A,
public CBase
{
public:
virtual void foo_A() { /* Do something... */}
};
Apparently this gives error:
C2259: 'CBaseExt_A': cannot instantiate abstract class...These errors refer to all IBase interface functions.
I know I can solve it the long way by delegating all IBase functions to CBase implementation:
class CBaseExt_A :
public IBaseExt_A,
public CBase
{
// IBase implementation:
public:
virtual void foo1() { CBase::foo1();}
virtual void foo2() { CBase::foo2();}
virtual void foo3() { CBase::foo3();}
virtual void foo4() { CBase::foo4();}
virtual void foo5() { CBase::foo5();}
// ...
virtual void fooN() { CBase::fooN();}
// IBaseExt_A implementation:
public:
virtual void foo_A() { /* At last - do what we came here for...*}
};
But this makes my small class CBaseExt_A become big and complex.
Is there a way how to avoid all this manual delegation coding?
Many thanks, PazO
You should use the following code:
interface IBase
{
virtual void foo() = 0;
......
};
class CBase : virtual public IBase
{
void foo() { }
......
};
interface IBaseExt_A : virtual public IBase
{
virtual void foo_A() = 0;
};
struct CBaseExt_A : public IBaseExt_A, public CBase
{
virtual void foo_A() { /* Do something... */ }
};
Note that both places where the IBase class is inherited should be marked as virtual.
I think you should specify one of the two inheritance to be virtual.
That is a diamond inheritance where
IBase is the top level
IBaseExt_A and CBase are the middle level
CBaseExt_A is the bottom level
so in CBaseExt_A you want to specify from which path implement the top level, I would say that you may want to specify CBase inheritance in IBaseExt_A to be public virtual instead of just public.
class CBaseExt_A :
public IBaseExt_A,
public virtual CBase
{
public:
virtual void foo_A() { /* Do something... */}
};
For code below, are there any other ways to access a method in base through interface?
struct Base {
void funct_base() {
printf("Common function for class Foo and class Bar\n");
}
};
struct IFoo {
virtual ~IFoo() {}
virtual void funct_a() = 0;
// would like to access Base::bunct_base() from here
};
struct Foo : public Base, public IFoo {
virtual void funct_a() {
printf("I am Foo:: funct A\n");
}
};
class IBar {
virtual ~IBar() {}
virtual void funct_a() = 0;
// would like to access Base::bunct_base() from here
};
class Bar : public Base, public IBar {
virtual void funct_a() {
printf("I am Bar:: funct A\n");
}
};
I know this can be done, but I just do not like the wrapper, it does not seem clean:
struct IBar {
virtual ~IBar() {}
virtual void funct_a() = 0;
virtual void funct_base() = 0;
};
struct Bar : public Base {
virtual void funct_a() {
printf("I am Bar:: funct A\n");
}
virtual void funct_base() {
Base::funct_base();
}
};
EDIT:
The question is, there is one base class, and two different derived classes that inherit from the same base class. Is there a way to access a base class method through derived class interface without adding a base class method wrapper?
Use a abstract base class IBase with a Abstract method funct_base and make the interface class a Virtual base classes of the classes Base, IFoo and IBar:
struct IBase {
virtual void funct_base() = 0;
};
struct Base : public virtual IBase {
virtual void funct_base() override { printf("Common function for class Foo and class Bar\n"); }
};
struct IFoo : public virtual IBase {
virtual void funct_a() = 0;
};
struct Foo : public IFoo, public Base {
virtual void funct_a() override { printf("I am Foo:: funct A\n"); }
};
class IBar : public virtual IBase {
virtual void funct_a() = 0;
};
class Bar : public IBar, public Base {
virtual void funct_a() override { printf("I am Bar:: funct A\n"); }
};
I have 3 interface (pure virtual) classes like this
class A {
virtual void M1() = 0;
virtual void M2() = 0;
};
class B : public A {
virtual void M3() = 0;
};
class C : public A {
virtual void M4() = 0;
};
I have the implementers like this
class Aimpl : A {
void M1 () override {};
void M2 () override {};
}
class Bimpl: public Aimpl, public B{
void M3() override {};
}
class Cimpl: public Aimpl, public C{
void M4() override {};
}
and
Bimpl b = Bimpl();
b.M2() // Error. M2 is ambigous. Can be from Aimpl or A
what's a simple way to fix this? I want to be able to pass around B or C in functions rather than Bimpl
Essentially, you have two different M2 methods in Bimpl: Aimpl::M2 and B::M2. You have run into the diamond-inheritance problem.
To fix it, you should use virtual inheritance. This question provides a very good overview. Essentially, you should use something like this:
class A {
virtual void M1() = 0;
virtual void M2() = 0;
};
class B : public virtual A {
virtual void M3() = 0;
};
class C : public virtual A {
virtual void M4() = 0;
};
class Aimpl : public virtual A {
void M1 () override {};
void M2 () override {};
};
class Bimpl: public virtual Aimpl, public virtual B {
void M3() override {};
};
class Cimpl: public virtual Aimpl, public virtual C {
void M4() override {};
};
Note that I'm not super super familiar with virtual inheritance, so this may or may not be the best way to apply virtual inheritance.
Please refer the following example.
using namespace std;
//Base interface
class IBase
{
public:
virtual void BaseMethod1() = 0;
virtual void BaseMethod2() = 0;
};
class IEntity1 : public IBase
{
public:
virtual void Entity1Method1() = 0;
virtual void Entity1Method2() = 0;
};
class Entity1 : public IEntity1
{
public:
Entity();
//IBaseMethods
void BaseMethod1();
void BaseMethod2();
//IEntityMethods
void Entity1Method1();
void Entity1Method2();
//EntityMethods
void Method1();
void Method2();
};
In the above example, for all other entities deriving from IBase needs to implement BaseMethod1() and BaseMethod2().Because of which lots of code duplication is happening? Is there anyway where we can avoid redundant implementation of IBase methods in entities deriving from it?
You can use virtual inheritance in combination with a default base implementation class to encapsulate your default base behavior, and have it be only inherited by the concrete classes you want, like follows:
using namespace std;
//Base interface
class IBase
{
public:
virtual void BaseMethod1() = 0;
virtual void BaseMethod2() = 0;
};
class IEntity1 : virtual public IBase
{
public:
virtual void Entity1Method1() = 0;
virtual void Entity1Method2() = 0;
};
class BaseImpl : virtual public IBase
{
public:
virtual void BaseMethod1()
{
...
}
virtual void BaseMethod2()
{
...
}
}
class Entity1 : public IEntity1, public BaseImpl
{
public:
Entity1();
//IEntityMethods
void Entity1Method1();
void Entity1Method2();
//EntityMethods
void Method1();
void Method2();
};
There is, however, a runtime cost associated with virtual inheritance. Multiple inheritance also comes with some structural issues, e.g. base class construction.
You can even have some fun with template classes to make your class composition more modular:
template<typename TEntity, typename TBaseImpl>
class ConcreteEntity: public TEntity, public TBaseImpl
{
public:
ConcreteEntity() {}
};
class ConreteEntity1 : public ConcreteEntity<IEntity1, BaseImpl>
{
public:
ConreteEntity1();
//IEntityMethods
void Entity1Method1();
void Entity1Method2();
//ConreteEntity1 Methods
void Method1();
void Method2();
};
You could make a function that is called in BaseMethod1() implementations that are the same.
Something like this:
void BaseMethod1_common();
class Entity1 : public IEntity1
{
public:
Entity();
//IBaseMethods
void BaseMethod1() { BaseMethod1_common(); }
void BaseMethod2();
//IEntityMethods
void Entity1Method1();
void Entity1Method2();
//EntityMethods
void Method1();
void Method2();
};
First of all IBase deserves a virtual destructor.
Declare it pure virtual and define IBase:BaseMethod1() and
IBase::BaseMethod1().
If your intention is to hide implementation, then the only option would be to release the code as a library and then share only the header file among the other developers.
Implementing a global function, or using multiple inheritance as suggested still mean that your implementation is exposed.
However, if the intent is to reduce coupling among the various classes, there's another option :
Create a class that has the actual shared implementation, and then another class which will be an interface to it.
This interface class will then be the base class for other derived entities.
Example code is shown below :
//First Header and Cpp file
class Base_private
{
public:
BaseImpl(arguments);
~BaseImpl();
void BaseMethod1() {
//Implementation
}
void BaseMethod2() {
//Implementation
}
};
//Second Header and Cpp file
class BaseInterface
{
public:
BaseInterface(arguments);
~BaseInterface();
void BaseMethod1() {
m_pBase->BaseMethod1();
}
void BaseMethod2() {
m_pBase->BaseMethod2();
}
private:
Base_private* m_pBase;
};
class Entity : public BaseInterface
{
public:
Entity(arguments);
~Entity();
void Method1();
void Method2();
};
I'm trying to do something like C# explicit interface implementation in unmanaged C++. I am able to do it so long as the function implementation is part of the class definition but I can't figure out how to get it to work with the function implementation in the source file.
Here's my test code:
class Base
{
public:
virtual void Func() = 0;
void CallFunc()
{
Func();
}
};
class Base1 : public Base
{
public:
virtual void Func() = 0;
};
class Base2 : public Base
{
public:
virtual void Func() = 0;
};
// This Works
class Multi : public Base1, public Base2
{
public:
virtual void Base1::Func()
{
puts("Base1::Func()");
}
virtual void Base2::Func()
{
puts("Base2::Func()");
}
};
// This does not
// 1>multipeinheritancetest.cpp(60): error C2509: 'Func' : member function not declared in 'Multi'
// 1> multipeinheritancetest.cpp(51) : see declaration of 'Multi'
// 1>multipeinheritancetest.cpp(65): error C2509: 'Func' : member function not declared in 'Multi'
// 1> multipeinheritancetest.cpp(51) : see declaration of 'Multi'
/*
class Multi : public Base1, public Base2
{
public:
virtual void Base1::Func();
virtual void Base2::Func();
};
void Multi::Base1::Func()
{
puts("Base1::Func()");
}
void Multi::Base2::Func()
{
puts("Base2::Func()");
}
*/
// This is a work-around for when I don't want to declare the full function in the header
/*
class Multi : public Base1, public Base2
{
public:
virtual void Base1::Func() { Base1_Func(); }
virtual void Base2::Func() { Base2_Func(); }
void Base1_Func();
void Base2_Func();
};
void Multi::Base1_Func()
{
puts("Base1_Func()");
}
void Multi::Base2_Func()
{
puts("Base2_Func()");
}
*/
void RunMultiTest()
{
Multi m;
m.Base1::CallFunc();
m.Base2::CallFunc();
}
Is there a way to do this and my syntax is just off or is this a Visual Studio bug or is this just not possible with C++?
The Base1::Func isn't valid in your "works" case either, it's just accepted by your compiler.
If you want two different functions call them two different names. If you want one function, use virtual inheritance:
EDIT: fixed from comment
class Base1 : public virtual Base
and
class Base2 : public virtual Base
and then remove the base qualification from the function override.