Override of virtual function ambiguous with diamond inheritance - c++

I have a diamond inheritance structure like:
class Card {
public:
virtual std::string info() const = 0;
}
class Color : public Card {
public:
virtual std::string info() const = 0;
}
class Deploy : virtual public Color {
public:
virtual std::string info() const = 0;
}
class Attack : virtual public Color {
public:
virtual std::string info() const = 0;
}
class Character : public Attack, public Deploy {
public:
std::string info() { return "My Info" };
}
But in the class Character it says to me:
override of virtual function "Card::info" is ambiguous
I want to have just one declaration of info in Character. How can I do it?

Apart from missing some ;s at the end of class definitions and the return statement of Character::info,
The main issue is that are missing the const qualifier from the definition of Character::info.
I would also add override the get help from the compiler if the method does not in fact override a base class method:
//-----------------vvvvv-vvvvvvvv----------------------
std::string info() const override { return "My Info"; };

Related

Can concrete functions from a derived class override virtual functions from a separate base class?

Is it possible to have concrete functions from a derived class override virtual functions from a separate base class? Like this:
// abstract Person
class I_Person
{
public:
virtual int age() = 0;
virtual int height() = 0;
};
// concrete person
class Person
{
public:
Person() = default;
int age();
int height();
}
class I_Worker : public I_Person
{
public:
virtual ~I_Worker() = default;
virtual void worker_func() = 0;
}
class Worker : public I_Worker, public Person
{
// override I_Person functions here with concrete Person functions
}
In my app, there are not just 2 functions in the Person class, there are more like 30. So Im trying to avoid redeclaring them in the concrete Worker class like this:
class Worker : public I_Worker, public Person
{
public:
int age() override {
return Person::age();
}
int height() override {
return Person::height();
}
void worker_func() override {}
};
Is there a way to do this or achieve a similar result?

Method of Abstract Class used by derived Class

I got an Abstract Baseclass which looks like this:
class AbstractClass {
public:
virtual ~AbstractClass() = 0 {}
std::string GetName() const { return m_Name; }
private:
std::string m_Name;
};
Now I got many derived Classes and I want to implement them like this
class DerivedClass1 : public AbstractClass{
public:
DerivedClass1() = default;
~DerivedClass1() = default;
private:
std::string m_Name = "DerivedClass1";
};
int main() {
DerivedClass1 class1;
std::cout << class1.GetName();
return 0;
}
I dont want to override GetName() everytime i derive a Class, is this possible?
Edit:
I got a Linker Error. Error LNK2019.
Use only one name, in the base class, and a constructor with a parameter:
class AbstractClass{
public:
AbstractClass(const std::string& name) : m_Name(name){}
std::string GetName() const { return m_Name; }
private:
std::string m_Name;
};
DerivedClass1 : public AbstractClass{
public:
DerivedClass() : AbstractClass("DerivedClass1") {}
};
int main(){
DerivedClass1 class1;
std::cout << class1.GetName();
return 0;
}
There seems to be no reason for making the base class abstract, but if you do need that, even a pure virtual destructor must have a definition, or you will get a linker error, because it's needed when destroying derived objects.
Also, if the destructor didn't exist, when would m_Name be destroyed?
class Abstract
{
public:
virtual ~Abstract() = 0;
};
Abstract::~Abstract() {}
This makes a class that can't be instantiated, but whose derived classes can still be destroyed.
That's not how you "override" GetName(). You can either make GetName() virtual and override it in your derived classes:
class AbstractClass {
public:
virtual ~AbstractClass() = default;
virtual std::string GetName() const { return "AbstractClass"; }
private:
std::string m_Name;
};
and:
class DerivedClass1 : public AbstractClass {
public:
DerivedClass() = default;
std::string GetName() const override { return "DerivedClass1"; }
};
Or you can set m_Name in your derived classes by passing it to the base class constructor:
class AbstractClass {
public:
AbstractClass(const std::string& name) : m_Name(name) {}
virtual ~AbstractClass() = default;
std::string GetName() const { return m_Name; }
protected: // protected not private
std::string m_Name;
};
and:
class DerivedClass1 : public AbstractClass {
public:
DerivedClass() : AbstractClass("DerivedClass1") {}
};
Or you can set it in the derived's class constructor:
class AbstractClass {
public:
virtual ~AbstractClass() = default;
std::string GetName() const { return m_Name; }
protected: // protected not private
std::string m_Name;
};
and:
class DerivedClass1 : public AbstractClass {
public:
DerivedClass() : AbstractClass() { m_Name = "DerivedClass1"; }
};
You get the link error because the destructor for AbstractClass needs to be defined even if it is empty.
AbstractClass::~AbstractClass()
{
// Compulsory virtual destructor definition,
// even if it's empty
}
LIVE on Wandbox
Regarding overriding getName: you do not have to. If you do not provide an implementation in the derived class, the one inherited one is used.
Code sugest that problem is how to get a class name? But this is not clearly stated in question (XY problem)
How to handle class name?
You can use RTTI:
class ClassName {
public:
virtual ~ClassName() {} // just to enable RTTI for all decendants
std::string getClassName() {
return typeid(*this).name();
}
};
https://wandbox.org/permlink/LvPdA37arMr0LFQW
But as you can see it adds some extra prefix (it is compiler depended). boost can clean it up:
https://wandbox.org/permlink/8XiB7yVOM0wYVxpl

A design qustion about C++ interface(pure virtual class)/multiple inheritance/virtual inheritance

I want to reconstruct my small 3d-engine, it is very small so i place all files in only one project.
now, i want to reconstruct it with interfaces, so i can disperse different modules to the different projects and build them as a dll.
when i do that, i have met a lot of difficulties in the basic design of framework code.
I want to design a 'Object Hierarchy' of my small engine, it is realized in the previous work. for example:
Object
Component
SceneComponent
StaticMeshComponent/SkelMeshComponent
D3DSkelComponent
...
but they are implement directly.
now, i want to use interface(pure virtual class), i have design the basic interfaces(for test ):
#include <cstdio>
#include <iostream>
#include <string>
using namespace std;
class IObject
{
public:
virtual std::string GetName() = 0;
};
class IMesh : public IObject
{
public:
virtual void Draw() = 0;
};
class IStaticMesh : public IMesh
{
public:
virtual void BuildSomeMesh() = 0;
};
class ISkeletalMesh : public IMesh
{
public:
virtual void PlayAnim( const std::string& strAnimName ) = 0;
};
class ID3DSkeletalMesh : public ISkeletalMesh
{
public:
virtual void LoadD3D( const std::string& strD3D ) = 0;
};
it looks like ok, but when i try to implement them, i find that it may be a impossible mission.
first, i can write a template class or normal class for IObject, eg:
template < typename TBase >
class TObject : public TBase
{
public:
virtual std::string GetName()
{
return m_strTest;
}
std::string m_strTest;
};
based on this TObject, I can implement a CMesh:
class CMesh : public TObject< IMesh >
{
public:
virtual void Draw()
{
cout<<"draw mesh" <<endl;
}
};
IMesh* pMesh = new CMesh(); // ok
IObject* pObj = pMesh; // ok
so far, it works well. but how to implement the CStaticMesh/CSkeletalMesh/CD3DSkeletalMesh?
it maybe like this:
class CStaticMesh : public CMesh, public IStaticMesh
{
public:
};
but i have two IObject base class, so i must change all "public xxx" to "virtual public xxx", it looks bad.
another question is CStaticMesh must implement all virtual member function of IStaticMesh, include:
virtual void Draw() = 0;
virtual void BuildSomeMesh() = 0;
even if there is a Draw in CMesh which is a base call of CStaticMesh.
ok, maybe i need a TMesh:
template < typename TBase >
class TMesh : public TObject< TBase >
{
public:
virtual void Draw()
{
cout<<"draw mesh" <<endl;
}
};
and implement CStaticMesh like this:
class CStaticMesh : public TMesh<IStaticMesh>
{
public:
virtual void BuildSomeMesh()
{
cout<<"Build Some Mesh!"<<endl;
}
};
it looks like ok, but how to implment CD3DSkeletalMesh? make a TSkeletalMesh? ok, it is crazy!!!
i think, this is abime.
which is the mistake in this design? how to change the design idea to avoid this dilemma? do you know a idea which can keep the inheritance hierarchy of those interfaces and implement easily?
if i use many virtual inheritance, is there any performance isuue?
You can solve this, as you mentioned, with virtual inheritance. This will create only one instance of a multiply inherited interface class in the hierarchy.
First the interfaces:
class IObject
{
public:
virtual std::string GetName() = 0;
};
class IMesh : virtual public IObject
{
public:
virtual void Draw() = 0;
};
class IStaticMesh : virtual public IMesh
{
public:
virtual void BuildSomeMesh() = 0;
};
class ISkeletalMesh : virtual public IMesh
{
public:
virtual void PlayAnim( const std::string& strAnimName ) = 0;
};
class ID3DSkeletalMesh : virtual public ISkeletalMesh
{
public:
virtual void LoadD3D( const std::string& strD3D ) = 0;
};
Then the implementations:
class CObject : virtual public IObject
{
public:
std::string GetName()
{
return m_strTest;
}
std::string m_strTest;
};
class CMesh : public CObject, virtual public IMesh
{
public:
void Draw()
{
cout<<"draw mesh" <<endl;
}
};
class CStaticMesh : public CMesh, virtual public IStaticMesh
{
public:
void BuildSomeMesh()
{
cout<<"Build Some Mesh!"<<endl;
}
};
...
For the performance implications of this, look at this question.

"cannot instantiate abstract class" Multiple inheritance and 3rd party interface

I have an existing project with the following class inheritance
class Base
{
public:
Base();
virtual ~Base();
void SetID(unsigned short);
virtual inline unsigned short GetID();
protected:
unsigned short id;
};
class Generic : public Base {
public:
Generic(const char *in_name);
const char* GetName() { return name; }
protected:
char name[30];
};
class Actor : public Generic
{
public:
Actor(const char *in_name);
~Actor();
void DoSomething(const char* str);
};
Now i created a separate project were i want to provide an interface that has to be implemented in order to use the functionality - i plan on reusing this project for other implementation.
class MyInterface
{
public:
virtual ~MyInterface() {}
// Our methods that need to implemented
virtual const char* GetName() = 0;
virtual void DoSomething(const char* str) = 0;
virtual unsigned short GetID() = 0;
};
Now i simply wanted to use this with my actor class e.g.
class Actor : public Generic, public MyInterface
however it fails to compile
'const char *MyInterface::GetName(void)' : is abstract see declaration of 'MyInterface::GetName'
'unsigned short MyInterface::GetID(void)' : is abstract see declaration of 'MyInterface::GetID'
error C2385: ambiguous access of 'GetName'
could be the 'GetName' in base 'Generic'
or could be the 'GetName' in base 'MyInterface'
The problem is probably that GetName is already implemented in Generic, and GetID is already implemented in Base - so in the child class Actor implementing the Interface is not possible because the compiler is not smart enough to realize there is already an implementation of these methods.
However, i found a workaround - but for this i would have to extend the header of the actor class which is not a nice thing - and i wanted to know if there is another approach - my fix is
class Actor : public Generic, public MyInterface
{
public:
Actor(const char *in_name);
~Actor();
void DoSomething(const char* str);
const char* GetName() { return Generic::GetName(); };
inline unsigned short GetID() { return Base::GetID(); };
};
Now this obviously will not work for varargs methods and i would have to implement existing methods and delegate to the parent again - is there a better solution?
EDIT For clarifications - the classes base,generic and actor exist in another project managed by others, modifications to these should be very limited. - I created a seperate project which creates a static LIB - to use functions of these in conjunction with the actor class - i created an interface to not have any dependency in my own project and also provide a reusable lib for other projects which would simply just need to implement this interface.
class Base
{
protected:
unsigned short id;
public:
void SetID(unsigned short);
virtual inline unsigned short GetID() { return id; }
virtual ~Base() {}
Base(): id() {}
};
class Generic
: public Base
{
protected:
char name[30];
public:
const char* GetName() { return name; }
Generic(const char* in_name): name() {}
};
class Actor
: public Generic
{
public:
void DoSomething(const char* str) {}
~Actor() {}
Actor(const char* in_name)
: Generic( name )
{}
};
class MyInterface
{
public:
// Our methods that need to implemented
virtual const char* name() const = 0;
virtual int id() const = 0;
virtual void doSomething( const char* str ) = 0;
virtual ~MyInterface() {}
};
template< class TpBase >
class MyInterfaceOn
: public virtual MyInterface
, public TpBase
{
public:
typedef TpBase Base;
private:
MyInterfaceOn& mutableSelf() const
{ return *const_cast<MyInterfaceOn*>( this ); }
public:
const char* name() const { return mutableSelf().Base::GetName(); }
int id() const { return mutableSelf().Base::GetID(); }
void doSomething(const char* str) { Base::DoSomething( str ); }
MyInterfaceOn( char const name[] )
: Base( name )
{}
};
class MyActor
: public MyInterfaceOn< Actor >
{
public:
MyActor( char const name[] )
: MyInterfaceOn< Actor >( name )
{}
};
int main()
{
MyInterface const& actor = MyActor( "NN" );
}

Inherit interfaces which share a method name

There are two base classes have same function name. I want to inherit both of them, and over ride each method differently. How can I do that with separate declaration and definition (instead of defining in the class definition)?
#include <cstdio>
class Interface1{
public:
virtual void Name() = 0;
};
class Interface2
{
public:
virtual void Name() = 0;
};
class RealClass: public Interface1, public Interface2
{
public:
virtual void Interface1::Name()
{
printf("Interface1 OK?\n");
}
virtual void Interface2::Name()
{
printf("Interface2 OK?\n");
}
};
int main()
{
Interface1 *p = new RealClass();
p->Name();
Interface2 *q = reinterpret_cast<RealClass*>(p);
q->Name();
}
I failed to move the definition out in VC8. I found the Microsoft Specific Keyword __interface can do this job successfully, code below:
#include <cstdio>
__interface Interface1{
virtual void Name() = 0;
};
__interface Interface2
{
virtual void Name() = 0;
};
class RealClass: public Interface1,
public Interface2
{
public:
virtual void Interface1::Name();
virtual void Interface2::Name();
};
void RealClass::Interface1::Name()
{
printf("Interface1 OK?\n");
}
void RealClass::Interface2::Name()
{
printf("Interface2 OK?\n");
}
int main()
{
Interface1 *p = new RealClass();
p->Name();
Interface2 *q = reinterpret_cast<RealClass*>(p);
q->Name();
}
but is there another way to do this something more general that will work in other compilers?
This problem doesn't come up very often. The solution I'm familiar with was designed by Doug McIlroy and appears in Bjarne Stroustrup's books (presented in both Design & Evolution of C++ section 12.8 and The C++ Programming Language section 25.6). According to the discussion in Design & Evolution, there was a proposal to handle this specific case elegantly, but it was rejected because "such name clashes were unlikely to become common enough to warrant a separate language feature," and "not likely to become everyday work for novices."
Not only do you need to call Name() through pointers to base classes, you need a way to say which Name() you want when operating on the derived class. The solution adds some indirection:
class Interface1{
public:
virtual void Name() = 0;
};
class Interface2{
public:
virtual void Name() = 0;
};
class Interface1_helper : public Interface1{
public:
virtual void I1_Name() = 0;
void Name() override
{
I1_Name();
}
};
class Interface2_helper : public Interface2{
public:
virtual void I2_Name() = 0;
void Name() override
{
I2_Name();
}
};
class RealClass: public Interface1_helper, public Interface2_helper{
public:
void I1_Name() override
{
printf("Interface1 OK?\n");
}
void I2_Name() override
{
printf("Interface2 OK?\n");
}
};
int main()
{
RealClass rc;
Interface1* i1 = &rc;
Interface2* i2 = &rc;
i1->Name();
i2->Name();
rc.I1_Name();
rc.I2_Name();
}
Not pretty, but the decision was it's not needed often.
You cannot override them separately, you must override both at once:
struct Interface1 {
virtual void Name() = 0;
};
struct Interface2 {
virtual void Name() = 0;
};
struct RealClass : Interface1, Interface2 {
virtual void Name();
};
// and move it out of the class definition just like any other method:
void RealClass::Name() {
printf("Interface1 OK?\n");
printf("Interface2 OK?\n");
}
You can simulate individual overriding with intermediate base classes:
struct RealClass1 : Interface1 {
virtual void Name() {
printf("Interface1 OK?\n");
}
};
struct RealClass2 : Interface2 {
virtual void Name() {
printf("Interface2 OK?\n");
}
};
struct RealClass : RealClass1, RealClass2 {
virtual void Name() {
// you must still decide what to do here, which is likely calling both:
RealClass1::Name();
RealClass2::Name();
// or doing something else entirely
// but note: this is the function which will be called in all cases
// of *virtual dispatch* (for instances of this class), as it is the
// final overrider, the above separate definition is merely
// code-organization convenience
}
};
Additionally, you're using reinterpret_cast incorrectly, you should have:
int main() {
RealClass rc; // no need for dynamic allocation in this example
Interface1& one = rc;
one.Name();
Interface2& two = dynamic_cast<Interface2&>(one);
two.Name();
return 0;
}
And here's a rewrite with CRTP that might be what you want (or not):
template<class Derived>
struct RealClass1 : Interface1 {
#define self (*static_cast<Derived*>(this))
virtual void Name() {
printf("Interface1 for %s\n", self.name.c_str());
}
#undef self
};
template<class Derived>
struct RealClass2 : Interface2 {
#define self (*static_cast<Derived*>(this))
virtual void Name() {
printf("Interface2 for %s\n", self.name.c_str());
}
#undef self
};
struct RealClass : RealClass1<RealClass>, RealClass2<RealClass> {
std::string name;
RealClass() : name("real code would have members you need to access") {}
};
But note that here you cannot call Name on a RealClass now (with virtual dispatch, e.g. rc.Name()), you must first select a base. The self macro is an easy way to clean up CRTP casts (usually member access is much more common in the CRTP base), but it can be improved. There's a brief discussion of virtual dispatch in one of my other answers, but surely a better one around if someone has a link.
I've had to do something like this in the past, though in my case I needed to inherit from one interface twice and be able to differentiate between calls made on each of them, I used a template shim to help me...
Something like this:
template<class id>
class InterfaceHelper : public MyInterface
{
public :
virtual void Name()
{
Name(id);
}
virtual void Name(
const size_t id) = 0;
}
You then derive from InterfaceHelper twice rather than from MyInterface twice and you specify a different id for each base class. You can then hand out two interfaces independently by casting to the correct InterfaceHelper.
You could do something slightly more complex;
class InterfaceHelperBase
{
public :
virtual void Name(
const size_t id) = 0;
}
class InterfaceHelper1 : public MyInterface, protected InterfaceHelperBase
{
public :
using InterfaceHelperBase::Name;
virtual void Name()
{
Name(1);
}
}
class InterfaceHelper2 : public MyInterface, protected InterfaceHelperBase
{
public :
using InterfaceHelperBase::Name;
virtual void Name()
{
Name(2);
}
}
class MyClass : public InterfaceHelper1, public InterfaceHelper2
{
public :
virtual void Name(
const size_t id)
{
if (id == 1)
{
printf("Interface 1 OK?");
}
else if (id == 2)
{
printf("Interface 2 OK?");
}
}
}
Note that the above hasn't seen a compiler...
class BaseX
{
public:
virtual void fun()
{
cout << "BaseX::fun\n";
}
};
class BaseY
{
public:
virtual void fun()
{
cout << "BaseY::fun\n";
}
};
class DerivedX : protected BaseX
{
public:
virtual void funX()
{
BaseX::fun();
}
};
class DerivedY : protected BaseY
{
public:
virtual void funY()
{
BaseY::fun();
}
};
class DerivedXY : public DerivedX, public DerivedY
{
};
There are two other related questions asking nearly (but not completely) identical things:
Picking from inherited shared method names. If you want to have rc.name() call ic1->name() or ic2->name().
Overriding shared method names from (templated) base classes. This has simpler syntax and less code that your accepted solution, but does not allow for access to the functions from the derived class. More or less, unless you need to be able to call name_i1() from an rc, you don't need to use things like InterfaceHelper.