Regarding the size of the derived class, is it better to have a "chain" of inheritance or inherit everything in the lowest derived class?
for example, what is better between:
class Base {
virtual void something() = 0;
};
class Derived1 {
// ...
};
class Derived2 : public Derived1, public Base {
// ...
};
and
class Base {
virtual void something() = 0;
};
class Derived1 : public Base {
// ...
};
class Derived2 : public Derived1 {
// ...
};
In the second case, will it have to store two vtable pointers and just one in the first case?
In the first case, I have a sizeof(Derived) lower that in the second case.
What you're seeing as far as i can see is simply an empty base class optimization.
See the godbolt I've prepared. When you don't have empty classes, the sizes are identical.
https://godbolt.org/z/HhiJz6
To specifically address your question Regarding the size of the derived class, is it better to have a "chain" of inheritance or inherit everything in the lowest derived class?
I guess if you have an empty base class in there, you could claim it to be "better" in terms of size of the class, but that is pretty dependent on the specifics of the way the class is defined that could change at any time.
I wouldn't base an inheritance structure on it unless i was really pressed for space.
Related
I have been struggling with this kind of problem for a long time, so I decided to ask here.
class Base {
virtual ~Base();
};
class Derived1 : public Base { ... };
class Derived2 : public Base { ... };
...
// Copies the instance of derived class pointed by the *base pointer
Base* CreateCopy(Base* base);
The method should return a dynamically created copy, or at least store the object on stack in some data structure to avoid "returning address of a temporary" problem.
The naive approach to implement the above method would be using multiple typeids or dynamic_casts in a series of if-statements to check for each possible derived type and then use the new operator.
Is there any other, better approach?
P.S.: I know, that the this problem can be avoided using smart pointers, but I am interested in the minimalistic approach, without a bunch of libraries.
You add a virtual Base* clone() const = 0; in your base class and implement it appropriately in your Derived classes. If your Base is not abstract, you can of course call its copy-constructor, but that's a bit dangerous: If you forget to implement it in a derived class, you'll get (probably unwanted) slicing.
If you don't want to duplicate that code, you can use the CRTP idiom to implement the function via a template:
template <class Derived>
class DerivationHelper : public Base
{
public:
virtual Base* clone() const
{
return new Derived(static_cast<const Derived&>(*this)); // call the copy ctor.
}
};
class Derived1 : public DerivationHelper <Derived1> { ... };
class Derived2 : public DerivationHelper <Derived2> { ... };
An alternative is to have a pure virtual CreateCopy() method in the common base that is implemented in each derived class.
After writing a test, I determined that the this pointer in an interface is not equal to the this pointer of the concrete class, meaning I can't just use a C-style cast on it.
class AbstractBase {...};
class AnInterface {
public:
AnInterface() {...} // need AbstractBase * here
~virtual AnInterface() {...} // and here
};
class Concrete : public AbstractBase, public AnInterface {};
My interface needs a base class pointer to the concrete class inheriting it in the constructor and destructor in order to handle interface related registration and deregistration.
Every concrete object that inherits the interface needs to inherit the abstract base class first, it is always first in the layout.
For the constructor it is not all that hard, I can add a pointer in the interface constructor and pass this from the concrete class. But the destructor doesn't have any parameters, so I am in the dark there.
The solutions I came up with so far come with overhead:
1 - store the pointer in the interface to be used in the destructor - adds in one pointer worth of memory overhead
class AnInterface {
public:
AnInterface(AbstractBase * ap) {...}
~virtual AnInterface() {...} // and here
private:
AbstractBase * aPtr;
};
...
Concrete() : AnInterface(this) {}
2 - create an abstract method in the interface and implement it to return this in the concrete class - adds in the overhead of indirection for the virtual call
class AnInterface {
virtual AbstractBase * getPtr() = 0;
};
class Concrete : public AbstractBase, public AnInterface {
AbstractBase * getPtr() { return this; }
};
3 - dynamic_cast is even worse
Is there a more efficient way to achieve this?
IMO if decoupling between the base class and the interface is really needed, both solution 1 and 2 have tolerable overheads, certainly nothing that will be a problem on contemporary hardware.
But since you say that the interface is designed to work with the functionality, provided in the base class, then maybe the decoupling is not a good thing.
I mean if the problem is with inheriting multiple interfaces which all inherit the base class, or the "dreaded diamond" problem with inheritance, you can simply use virtual inheritance.
All of your concerns seem like micro-optimizations. Assuming you truly can't separate out your interface from your implementation (in which case, why are you using interfaces in the first place?) I would just use dynamic_cast and be done with it, even though it's pretty heavyweight. If I were stuck on a platform where RTTI isn't an option then I'd use option 2.
Your design has some flaws.
You should consider using CRTP as from the Mixin aspect, which saves you from keeping an extra pointer of the concrete derived.
template<typename Derived>
class AnInterface {
public:
AnInterface() {
Derived* derived = static_cast<Derived*>(this);
AbstractBase* abstractBase = static_cast<AbstractBase*>(derived);
} // have AbstractBase * here
~virtual AnInterface() {...} // and here
};
class Concrete
: public virtual AbstractBase
, public AnInterface<Concrete> {
AbstractBase * getPtr() { return this; }
};
I have a class Base1 that contains an array of objects of a different class Base2. I would like to have a derived class Derived1 that inherits everything from Base1 except the array is of type Derived2 (which is a derived class of Base2). For example, something like this:
class Base2{
int a2;
};
class Derived2: public Base2{
int b2;
};
class Base1{
Base2* list;
};
class Derived1: public Base1{
Derived2* list;
};
My understanding is that in the above example, an object of Derived1 would actually have TWO arrays:
list
and
Base1::list
which I don't want.
The idea is that all the functionality of Base1 should still work for a Derived1 object since Derived2 "is a" Base2. It would be really dirty, but I guess I could just delete[] the Base1::list array in the Derived1 constructor.
Does anyone see a solution to this? It seems like something that would happen frequently, and I cannot believe a simple solution does not exist. Would using templates work? My thought was no, since all the functionality in Base1 and Derived1 need to know that they are dealing with Base2 and Derived2 objects, respectively.
What do you expect to happen when someone downcasts a Derived1 class to Base1? It will crash when list is used after you sabotage the base class. The best thing is to continue to use the base class's list, and make sure only objects of type Derived2 are put in the list. If the content of the list can't be externally modified, that would work and be safe.
Yes, I know there's a lot more to say about this but let's take it one step at a time.
What you are trying to do, in general case, seems dangereous, but I assume you know the risks ;)
I can suggest two solutions:
Option 1:
You can hide the actual pointer in a protected section and provide an access function.
class Base1 {
protected:
void *ptr
public:
Base2 *list() {return (Base2*)ptr;}
};
class Derived1 : public Base1 {
public:
Derived2 *list() {return (Derived2*)ptr;}
};
Basically, the Base2::list will be hidden by the Derived2::list. Note, you cannot make them virtual and benefit from the virtuality. The return type has to be known at compile-time.
Option 2:
You can use templated base class.
template <typename T>
class List {
public:
T *list
//implement all functionality which is common, regardless of the type T
};
class Base1 : public List<Base2> {
//specifics for Base2 type
};
class Derived1 : public List<Derived2> {
//specifics for Derived2
};
Note that in this construct, Base1 and Derived1 are not directly related, but have a common ancestor instead.
I'd remove the array of Base2 from Base1, and create a new class with the list:
class Base2{
int a2;
};
class Derived2: public Base2{
int b2;
};
class Base1{
};
class Base1WithList : public Base1{
Base2* list;
};
class Derived1: public Base1{
Derived2* list;
};
I dont think there exists anything simple that solves your problem.
I would have used one of the following ways -
OPTION 1
Hide the Base2* list (in base1 class) by making it private, and save it getting inherited by the derived class (derived1). And of course, define a getter function in base1 class to access the list.
OPTION 2
Just change the type of list in base1 class to (a pointer to) Derived2 , and rely on the fact that a pointer to a derived class is type-compatible with a pointer to its base class.
OPTION 3
Forget inheritance and use templates. You will just need to specify the type (Base2* or Derived2*) while instantiating an object, and life will be beautiful again.
The question comment from #ildjarn gave me the solution to a similar problem:
class Base {
Base* children;
};
class Derived : public Base {
int answer;
public:
void give_answer() {
this->answer == 42;
for(auto child : this->children) {
// at this point `give_answer` is not defined for items of `children`
child->give_answer(); // -> error: ‘class Base’ has no member named ‘give_answer’
}
};
};
The solution is to introduce a virtual function into Base:
class Base {
Base* children;
public:
virtual void give_answer();
}
virtual void give_answer() = 0; would also work, making Base abstract.
(This example is a bit contrived, because why even have Base, but in my use case Derived is actually Derived<T>, and Base is a whole tree implementation.)
I have been struggling with this kind of problem for a long time, so I decided to ask here.
class Base {
virtual ~Base();
};
class Derived1 : public Base { ... };
class Derived2 : public Base { ... };
...
// Copies the instance of derived class pointed by the *base pointer
Base* CreateCopy(Base* base);
The method should return a dynamically created copy, or at least store the object on stack in some data structure to avoid "returning address of a temporary" problem.
The naive approach to implement the above method would be using multiple typeids or dynamic_casts in a series of if-statements to check for each possible derived type and then use the new operator.
Is there any other, better approach?
P.S.: I know, that the this problem can be avoided using smart pointers, but I am interested in the minimalistic approach, without a bunch of libraries.
You add a virtual Base* clone() const = 0; in your base class and implement it appropriately in your Derived classes. If your Base is not abstract, you can of course call its copy-constructor, but that's a bit dangerous: If you forget to implement it in a derived class, you'll get (probably unwanted) slicing.
If you don't want to duplicate that code, you can use the CRTP idiom to implement the function via a template:
template <class Derived>
class DerivationHelper : public Base
{
public:
virtual Base* clone() const
{
return new Derived(static_cast<const Derived&>(*this)); // call the copy ctor.
}
};
class Derived1 : public DerivationHelper <Derived1> { ... };
class Derived2 : public DerivationHelper <Derived2> { ... };
An alternative is to have a pure virtual CreateCopy() method in the common base that is implemented in each derived class.
I would like to use interfaces in c++ like in java or in c#. I decided to use purely abstract classes with multiple inheritance, but something is terribly wrong when I specialize the interface:
class Interface
{
public:
virtual int method() = 0;
};
// Default implementation.
class Base: virtual public Interface
{
public:
virtual int method() {return 27;}
};
// specialized interface
class Interface2: public Interface
{
public:
virtual int method() = 0;
// some other methods here
};
// concrete class - not specialised - OK
class Class: public virtual Interface, public virtual Base
{
};
// concrete class - specialised
class Class2: public Interface2, public Base
{
};
int main()
{
Class c;
Class2 c2;
return 0;
}
Warning 1 warning C4250: 'Class' : inherits 'Base::Base::method' via dominance 30
Error 2 error C2259: 'Class2' : cannot instantiate abstract class 42
What is the proper way to do this?
Class2 inherits from an abstract class (Interface2) but does not implement the pure virtual method, so it remains as an abstract class.
Heh heh, this problem tickles something buried deep in my head somewhere. I can't quite put my finger on it but I think it's to do with defining an interface heirarchy and then inheriting both an interface and an implementation. You then avoid having to implement all functions with by forwarding calls to a base class. I think.
I think this simple example shows the same thing, but is maybe a bit easier to understand because it uses things that can be easily visualized: (please forgive the struct laziness)
#include <iostream>
using namespace std;
struct Vehicle
{
virtual void Drive() = 0;
};
struct VehicleImp : virtual public Vehicle
{
virtual void Drive()
{
cout << "VehicleImp::Drive\n";
}
};
struct Tank : virtual public Vehicle
{
virtual void RotateTurret() = 0;
};
struct TankImp : public Tank, public VehicleImp
{
virtual void RotateTurret()
{
cout << "TankImp::RotateTurret\n";
}
// Could override Drive if we wanted
};
int _tmain(int argc, _TCHAR* argv[])
{
TankImp myTank;
myTank.Drive(); // VehicleImp::Drive
myTank.RotateTurret(); // TankImp::RotateTurret
return 0;
}
TankImp has essentially inherited the Tank interface and the Vehicle implementation.
Now, I'm pretty sure this is a well known and acceptable thing in OO circles (but I don't know if it has a fancy name), so the dreaded diamond thing is ok in this case, and you can safely suppress the dominance warning because it's what you want to happen in this case.
Hope that somehow helps point you in the right direction!
BTW, your code didn't compile because you hadn't implemented the pure virtual "method" in Class2.
EDIT:
Ok I think I understand your problem better now and I think the mistake is in Interface2. Try changing it to this:
// specialized interface
class Interface2: public virtual Interface // ADDED VIRTUAL
{
public:
//virtual int method() = 0; COMMENTED THIS OUT
// some other methods here
};
Interface2 should not have the pure virtual defintion of method, since that is already in Interface.
The inheritance of Interface needs to be virtual otherwise you will have an ambiguity with Base::method when you derive from Interface2 and Base in Class2.
Now you should find it will compile, possibly with dominance warnings, and when you call c2.method(), you get 27.
Based on this comment
If the method is not reimplemented in Class2 or Class (it is not in
this case) Base::method() will be called. Otherwise the reimplementation
will be called. There is an interface hierarchy with a common base
dumb implementation.
– danatel 16 mins ago
That's not what you got, you don't have a common base, you've got
Interface -> Interface2 -> Class2
Interface -> Base -> Class2
The interface is not 'merged' in the derivation tree, interface2 does not inherit virtually from interface, so it'll have its own interface super class.
It's like the pure virtual method() exists twice in Class2, once implemented via Class, and once not-implemented.
And even if you had inherited virtually, the common base (Interface) still would not have an implementation
If Base contains trivial operations that should be usuable in the whole hierarchy, then why not have Base as your startpoint? (even if still pure virtual with an implementation).
If this was just a very simple example to make the question short, something like the Bridge Pattern might be more usefull. But it's hard to guide you further without knowing more.
You should also look at defining a virtual destructor in your Interface if you might be deleting using an Interface or Base pointer.
Without a virtual destructor you will have problems if you do something like:
Base *b = new Class2();
delete b;
Regarding Class: All you need to do is derive Class from Base -- the fact that it implements Interface is implied, and in fact, inescapable:
class Class: public Base // virtual inheritance is unnecessary here
{
};
Class will inherit method() from Base as desired.
Regarding Class2:
Disclaimer: Negative result ahead
Based on your comment on Tom's answer, I thought I had the answer for Class2:
// concrete class - specialised
class Class2: public Interface2, public Base
{
public:
using Base::method; // "Imports" all members named "method" from Base
};
But actually, this doesn't work. Grovelling through the C++ standard reveals that
section 7.3.3, paragraph 14 explains that using can't be used to resolve ambiguous accesses to inherited members:
... [Note: because a using-declaration designates a base class member (and not a member subobject or a member function of a base class subobject), a using-declaration cannot be used to resolve inherited member ambiguities. ...]
It seems that the only way to get the desired behaviour in Class2 is to manually forward the method:
// concrete class - specialised
class Class2: public Interface2, public Base
{
public:
virtual int method() { return Base::method(); }
};
Regarding virtual inheritance: You don't need it for Class's declaration, but you probably do need it for Interface2's declaration to ensure that Class2 only has a single subobject of type Interface -- as it stands, every Class2 object has two subobjects of this type. (Although that won't cause problems if Interface is in fact a pure interface, lacking member variables.) If it helps, draw a diagram: every time a base class appears without the keyword virtual, it appears as a distinct object; all base classes that appear with the keyword virtual are condensed into one object.
[UPDATE: markh44's excellent answer shows that the above approach (of making Interface2 inherit virtually from Interface) will in fact allow Class2 to automatically inherit the implementation of method() from Base! Problem solved!]
This answer in a different forum seems to tackle the exact problem you mention.
In general, you should avoid the diamond inhertance pattern:
Interface
/ \
Base Interface2
\ /
Class2
This will cause you call kinds of grief down the road if you're not careful. Ambiguity will bite you.
In your specific instance there's no need for Interface2 to inherit from Interface. Interface2 doesn't need to specify "method" since it's abstract. Remove the inheritance between Interface and Interface2 to break the diamond. Then you're hierarchy looks like:
Interface Interface Interface2
| | |
Base Base |
| \ /
Class Class2
And your implementation looks like:
// concrete class - not specialised - OK
class Class: public Base
{
};
// concrete class - specialised
class Class2: public Base, public Interface2
{
virtual int method() {return 35;}
virtual void Inteface2Method { ... }
};