I'll try to make my intentions clear since there may be more than one approach to this. To start, I have an abstract base class FooBase with a virtual function SayHi(). Foo1 is one of many derived classes.
class FooBase {
public:
virtual void SayHi() = 0;
};
class Foo1 : public FooBase {
public:
virtual void SayHi() {
std::cout<<"Foo1 says Hi\n";
}
};
I also have a Component class and sometimes I would like to implement Foo.. classes as Components. I've used a template class so that any subclass of FooBase can have a Component wrapper.
class FooComponentBase : public Component {
public:
virtual FooBase& GetFoo() = 0;
};
template <class T>
class FooComponent : public FooComponentBase {
private:
T m_foo;
public:
virtual FooBase& GetFoo() {return m_foo;}
};
Now FooComponentBase is an interface to components containing any subclass of FooBase:
void DoTest() {
FooComponentBase* pFooComponent = new FooComponent<Foo1>;
pFooComponent->GetFoo().SayHi(); // "Foo1 says Hi"
delete pFooComponent;
}
So far so good, this works. But it might be neater if FooComponent were inherited from FooBase, so we don't need to go through GetFoo() to access FooBase's methods.
// Inherited version
class FooComponentBase : public Component {};
template <class T>
class FooComponent : public FooComponentBase, public T {};
Unfortunately, FooComponentBase has no access to FooBase even though all of its derived classes do;
void DoTest() {
FooComponentBase* pFooComponent = new FooComponent<Foo1>;
pFooComponent->SayHi(); // Error, FooComponentBase has no SayHi() function
delete pFooComponent;
}
I can't find a way to make this work. It seems like there ought to be a way, maybe using virtual inheritance;
class FooComponentBase : public Component, virtual public FooBase {};
But that won't compile either, since we can't instantiate an abstract class. I hope my intention is clear, I'd like to make FooComponentBase an abstract base class, like FooBase but with Component inheritance, so I can use it to access every flavor of FooComponent.
Is there a neat way to do this?
If you use virtual inheritance in one place, you have to use it everywhere if you want that same base implementation to be used:
class Foo1 : public virtual FooBase {
The other way, which is not as nice but might work out for you, would be to implement all of FooBase's functions in FooComponent:
class FooComponentBase : public Component, public FooBase {
};
template <class T>
class FooComponent : public FooComponentBase {
private:
T m_foo;
public:
void SayHi() {m_foo.SayHi();}
};
Or even:
class FooComponentBase : public Component, public FooBase {
};
template <class T>
class FooComponent : public FooComponentBase, public T {
public:
void SayHi() {T::SayHi();}
};
Related
I have a naive C++ inheritance class question. I have one base class Base, two derived classes DerivedA and DerivedB and two other distinct classes A and B which share the names of some methods.
Ideally I would like to design methods in the base class that use the methods of A and B. My attempt is the following
#include <cstdio>
class A{
public :
A(){};
void speak(){printf("hello A\n");};
};
class B{
public :
B(){};
void speak(){printf("hello B\n");};
};
class Base{
public:
Base(){};
void method(){property.speak();}
A property;
};
class DerivedA : public Base{
public:
using Base::Base;
A property;
};
class DerivedB : public Base{
public:
using Base::Base;
B property;
};
int main(int argc, char *argv[]){
DerivedA da;
DerivedB db;
da.property.speak();
db.property.speak();
// Attempting to call the shared method on the two distinct properties
da.method();
db.method();
}
Could you point me to a better design ? I suspect I should use templates but I am not sure how.
There are several options with different advantages and disadvantages.
You can make the base class a template like this:
template<class Property>
class Base{
public:
Base(){};
void method(){property.speak();}
Property property;
};
class DerivedA : public Base<A>{
};
class DerivedB : public Base<B>{
};
It is clear and simple, but notice that DerivedA and DerivedB in this case have no common base class, so you can't, e.g. put pointers to them in the same container.
You can use polymorphism.
class Base{
public:
virtual ~Base() {}
virtual void method() = 0;
};
class DerivedA : public Base{
public:
A property;
void method() override { property.speak(); }
};
class DerivedB : public Base{
public:
B property;
void method() override { property.speak(); }
};
This is a bit more complex, involves some code duplication and requires more resources (to store virtual table e.g.), but now the classes really have a common ancestor.
Combine templates and polymorphism
class Base{
public:
virtual ~Base() {}
virtual void method() = 0;
};
template<class Property>
class Derived: public Base {
public:
Property property;
void method() override { property.speak(); }
};
using DerivedA = Derived<A>;
using DerivedB = Derived<B>;
This is actually option #2, but with no code duplication: we make the compiler generate code for us using templates.
Other options. There may be other more specialized options depending on your requirements.
I was wondering what was the best way to achieve code reuse by inheritance in a COM application.
The Problem
It came to my understanding that the virtual inheritance model of C++ cannot by used in a COM environment because it is not language independent.
In pure C++ a class hierarchy could look something like the following:
interface IBase {
virtual void BaseMethod() = 0;
};
interface IDerived : virtual IBase {
virtual void DerivedMethod() = 0;
};
class CBase : public virtual IBase {
public:
virtual void BaseMethod() override { /* Do something */ }
};
class CDerived : public IDerived, public CBase {
public:
virtual void DerivedMethod() override { /* Do something */ }
};
This results in the following hierarchy:
IDerived and CBase both inherit virtually from IBase.
Since virtual inheritance is not available in COM, the class hierarchy would rather look something like this:
interface IBase {
virtual void BaseMethod() = 0;
};
interface IDerived : IBase {
virtual void DerivedMethod() = 0;
};
class CBase : public IBase {
public:
virtual void BaseMethod() override { /* Do something */ }
};
class CDerived : public IDerived, public CBase {
public:
virtual void DerivedMethod() override { /* Do something */ }
};
This results in the following hierarchy:
At first glance, there seems to be a problem with the ambiguity of IBase. This can be easily resolved by implementing the IUnknown::QueryInterface method.
The real problem is, how can CDerived inherit the implemented methods of IBase from CBase, namely CBase::BaseMethod?
In the case of virtual inheritance, CBase::BaseMethod can be inherited by dominance, but without virtual inheritance this cannot happen: In CDerived, the method CBase::IBase::BaseMethod is defined, however the method IDerived::IBase::BaseMethod is not, resulting in the class CBase still being abstract and not thus not eligible for instantiation.
One way, to resolve this would be to override the method BaseMethod in CDerived once again:
class CDerived : public IDerived, public CBase {
public:
virtual void BaseMethod() override { CBase::BaseMethod(); }
virtual void DerivedMethod() override { /* Do something */ }
};
Does this have any performance implications? Is there a better way of achieving what I want? Doesn't the repeated override of the function in CDerived defeat the whole idea of inheritance?
ATL widely uses a technique that goes like this:
template <typename Itf>
class IBaseImpl : public Itf {
public:
void BaseMethod() override;
};
class CBase : public IBaseImpl<IBase> {};
class CDerived : public IBaseImpl<IDerived> {
public:
void DerivedMethod() override;
};
Now you have straight-line inheritance: IBase <- IDerived <- IBaseImpl<IDerived> <- CDerived.
I'm having trouble passing a class DerivedObject (part of class DerivedClass derived from template class BaseClass) derived from BaseObject (part of template class BaseClass) as a template argument to template class BaseClass.
This way, both Base and Derived classes have the access to the object pool, that can contain derived objects. This sounds a bit confusing, so here is the example:
template <class TDerivedClass, class TDerivedObject>
class BaseClass
{
protected:
class BaseObject
{
// Class implementation
}
void foo()
{
static_cast<TDerivedClass*>(this)->foo();
}
std::vector<TDerivedObject*> m_objectPool;
};
The above is the base class implementation.
error C2065: 'DerivedObject' undeclared identifier
The above error is cause by the first line of the class definition bellow:
class DerivedClass : public BaseClass<DerivedClass, DerivedClass::DerivedObject>
{
protected:
class DerivedObject : public BaseObject
{
// Class implementation
}
void foo()
{
// Method implementation
}
};
Is there a way to do this? If not, is there a better solution that would give me the same / similar functionality?
At this point
class DerivedClass : public BaseClass<DerivedClass, DerivedClass::DerivedObject>
The compiler has not seen DerivedClass::DerivedObject so you get an undeclared identifier error. As they type has not been seen you cannot use it as a template parameter. You don't get one for DerivedClass as you already have declared DerivedClass as a class.
You could change you base class and have it store a std::vector<BaseObject*> in it and if you do that then you can change your code to:
template <class TDerivedClass>
class BaseClass
{
protected:
class BaseObject
{
// Class implementation
};
void foo()
{
static_cast<TDerivedClass*>(this)->foo();
}
std::vector<BaseObject*> m_objectPool;
};
class DerivedClass : public BaseClass<DerivedClass>
{
protected:
class DerivedObject : public BaseObject
{
// Class implementation
};
void foo()
{
// Method implementation
}
};
Here is one way of doing something similar to what was requested:
#include <vector>
using std::vector;
template <class TDerivedClass, class TDerivedObject>
class BaseClass
{
public:
class BaseObject
{
// Class implementation
};
protected:
// void foo()
// {
// static_cast<TDerivedClass*>(this)->foo();
// }
// std::vector<TDerivedObject*> m_objectPool;
};
class DerivedClass;
class DerivedObject : public BaseClass<DerivedClass, DerivedObject>::BaseObject
{
// Class implementation
};
class DerivedClass : public BaseClass<DerivedClass, DerivedObject>
{
public:
void foo()
{
// Method implementation
}
};
From your example code, I get the impression that you want to provide different implementations for different base classes. Is there any special reason for using templates? If not, you could use classic polymorphism instead:
class BaseClass
{
class BaseObject {};
virtual ~BaseClass() {} // <- do not forget to provide virtual dtor!
virtual void foo() = 0;
std::vector<BaseObject*> m_objectPool;
};
class DerivedClass : public BaseClass
{
class DerivedObject : public BaseObject {/*...*/};
virtual void foo(){/*...*/}
};
Again, BaseObject would offer virtual or pure virtual functions - as you need.
One thing, however, you lose this way: the guarantee that in the vector there are always the objects of one specific BaseObject sub-type. If this matters for you, you could protect the pool and only allow to add new BaseObjects via DerivedClass. If this is not applicable, I might think up another solution from within BaseClass.
If you do not mind having the DerivedObject structure separately from the DerivedClass you may do something like that:
template <class T>
struct ObjectTypeTrait
{
static_assert(sizeof(T) == 0, "undefined trait");
};
template <class TDerivedClass>
class BaseClass
{
protected:
class BaseObject
{
// Class implementation
};
void foo()
{
static_cast<TDerivedClass*>(this)->foo();
}
std::vector<typename ObjectTypeTrait<TDerivedClass>::obj*> m_objectPool;
};
class DerivedClass;
class DerivedObject
{
// Class implementation
};
template<>
struct ObjectTypeTrait<DerivedClass>
{
using obj = DerivedObject;
};
class DerivedClass : public BaseClass<DerivedClass>
{
protected:
void foo()
{
// Method implementation
}
};
I do not claim this to be very brilliant solution, but you can get the idea - using type traits or typedefs
Consider following hierarchy:
class Interface {
public:
virtual void foo() = 0;
};
class SubInterface: public Interface {
public:
virtual void bar() = 0;
};
class Base: public Interface {
public:
void foo() {};
};
class Impl: public SubInterface, public Base {
public:
void bar() {};
};
There are several sub interfaces which offer other methods in addition to foo().
There can be several implementing classes to a sub interface.
foo() is always implemented the same way.
Here is an example which simulates how these classes would be used:
int main() {
SubInterface* view1 = new Impl(); // Error! Interface::foo() is pure virtual within Impl
view1->foo();
view1->bar();
Interface* view2 = view1;
view2->foo();
}
Why can't the compiler see that Interface::foo() is implemented in Base which Impl inherits from?
I figured that I could implement foo() in Impl explicitly and delegate the call to Base like this:
class Impl: public SubInterface, public Base {
public:
void foo() {
Base::foo();
}
void bar() {};
};
However, I would have to do that for all classes which implement a sub interface, so this way isn't exactly ideal. Is there a better solution?
SubInterface and Base should inherit virtually from Interface otherwise you are creating ambiguity in form of the dreaded diamond
Basically, what happens is that Impl contains two 'instances' of Interface.
Here is why - follow the diagram:
Must virtual methods be always implemented in derived class?
Can I write something like this?
<!-- language: lang-cpp -->
class BaseInterface
{
public:
virtual void fun_a() = 0;
virtual void fun_b() = 0;
virtual ~BaseInterface();
};
class Derived : public BaseInterface
{
void fun_a() { ... };
};
class FinalClass : public Derived
{
void fun_b() { ... };
}
int main()
{
FinalClass test_obj;
test_obj.fun_a(); // use Derived implementation or fail ???
test_obj.fun_b(); // use own implementation
BaseInterface* test_interface = new FinalClass();
test_interface->fun_a(); // fail or ok ???
test_interface->fun_b();
}
Is the code above correct?
Does another virtual method outflank exist?
Pure virtual methods always must be reimplemented in derived class?
Actually a derived class which is going to be instantiated.
In your code, you didn't make an object from Derived so it's OK.
Can i write something like this?
Yes.
You had some minor errors that I corrected them:
class BaseInterface
{
public:
virtual void fun_a() = 0;
virtual void fun_b() = 0;
virtual ~BaseInterface() {}; // You forget this
};
class Derived : public BaseInterface
{
public:
void fun_a() {} // This should be public as its base
};
class FinalClass : public Derived
{
public:
void fun_b() {} // This should be public as its base
};
int main()
{
FinalClass test_obj;
test_obj.fun_a();
test_obj.fun_b();
BaseInterface* test_interface = new FinalClass();
test_interface->fun_a();
test_interface->fun_b();
}
It makes Derived also an abstract class which you cannot instantiate, seeing you don't implement all the virtual functions from it's base, it becomes an abstract class you cannot directly instantiate.
See here: liveworkspace.org/code/6huYU$10
For the rest, your code should work.
Code is correct.
There is no special concept for interface in C++. All are classes. Some of the class methods can be pure virtual. It only means that compiler cannot create an instance of such class.