The scenario generating this is quite complex so I'll strip out a few pieces and give an accurate representation of the classes involved.
/* This is inherited using SI by many classes, as normal */
class IBase
{
virtual string toString()=0;
};
/* Base2 can't inherit IBase due to other methods on IBase which aren't appropriate */
class Base2
{
string toString()
{
...
}
};
/* a special class, is this valid? */
class Class1 : public IBase, public Base2
{
};
So, is this valid? Will there be conflicts on the toString? Or can Class1 use Base2::toString to satisfy IBase?
Like I say there are lots of other things not shown, so suggestions for major design changes on this example are probably not that helpful... though any general suggestions/advice are welcome.
My other thought was something like this:
class Class1 : public IBase, public Base2
{
virtual string toString()
{
return Base2::toString();
}
};
This builds and links, but I've no idea if it has hidden bugs.
You can fix this using "virtual inheritance".
Consider creating a common base class that only defines a pure virtual toString method (or, in reality, pure virtual version of whatever methods it makes sense for both IBase and Base2 to have), e.g.
class Stringable {
public:
virtual string toString() = 0;
};
Then, have both IBase and Base2 inherit from this Stringable class:
class IBase : public Stringable
{
};
class Base2 : public Stringable
{
public:
virtual string toString()
{ ... }
};
Now this as it is still won't work because Class1 will have inherited two copies of the Stringable base class, only one of which has an implementation for toString in its inheritance hierarchy. This is known as the "dreaded diamond". However, if IBase and Base2 were to inherit virtually from Stringable, like this:
class IBase : virtual public Stringable
{
};
class Base2 : virtual public Stringable
{
public:
virtual string toString()
{ ... }
};
Then this tells the compiler that there should only be one common Stringable base class even if IBase and Base2 are both inherited by one class, which is exactly what you want, because then the Base2::toString is used for Class1.
Your second idea has no "hidden bugs", but is somewhat of a pain in the butt to implement repeatedly, as you probably realize.
This should work just fine.
You're properly overriding the IBase interface to provide a definition of ToString() that will be forwared up to Base2::ToString().
Note that Base2 doesn't declare toString() as virtual, so Class1 can't override the behavior of Base2::ToString. No ambiguity there.
And, in addition, this is not the classic diamond problem in multiple inheritance solved by virtual inheritance because they don't share a base class.
Related
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.
Suppose you have two functions fun1 and fun2. there are two classes der1 and der2. Both der1 and der2 implement fun1, but only der2 implements fun2. But i need to have polymorphic behavior with a base pointer to both der1 and der2. Does it make sense to have both these function in a base class (Abstract) even though only der2 will use both?
der1 and der2 are related and I think der2 should contain der1. But even then the base class will need to declare both fun1 and fun2. How do I achieve ISP? Does below code looks fine or is there a way to restructure it in a better way?
class base // Abstract
{
public:
virtual void fun1() {//default implementation}
void fun2(){ // used by only der2}
};
class der1 : public base
{
//this also have fun2 as its defined in base.
}
class der2 : public base
{
// should implement fun1 and fun2 both
public:
void fun2() { //implements fun2.}
}
The Interface Segregation Principle addresses the problem of client functions or classes using only a subset of all the methods in an interface they depend on. For example, imagine the following case:
In this case, both "Client" classes depend on the whole "BigInterface" API while they only really need a subset of methods. The simplest solution in a case like this is to "split" the big interface and create cohesive ones, e.g. :
In your particular case, it depends on who uses der1, der2 and base. It is hard to know if your code looks fine without more context information, but assuming that your client classes depend on base even though they only need either fun1 or fun2, you should apply a similar recipe as in the example and split your interface in two.
Hope that it helps :)
No, it doesn't make sense to have both functions in one base class, if there is a derived class which doesn't implement both functions. That would fail the Liskov Substitution Principle.
I suggest a hierarchy of interfaces:
struct base1
{
virtual void fun1();
};
struct base2 : public base1
{
virtual void fun2();
};
class der1 : public base1
{
public:
virtual void fun1() override;
};
class der2 : public base2
{
public:
virtual void fun1() override;
virtual void fun2() override;
};
A base1* can point to either a der1 or a der2, and therefore only has fun1.
A base2* has both fun1 and fun2, and therefore can only point to a der2.
I struggled to describe the problem succinctly in the title, so please recommend if you understand the issue and have a better title.
I have produced a stripped down version of my problem, its as small as I can get it, and as a result all functions are defined inline, so please excuse, actual code is not like this.
This is my structure:
class iobject
{
public:
virtual bool isValid (void) = 0;
};
class object : virtual public iobject
{
public:
object (void) { }
virtual ~object () {}
virtual bool isValid (void) { return true; }
};
So above, an interface + implementation which simply tracks whether an object is valid or not... imagine that all objects in an engine/system will derive from this single object.
class ibase : public virtual iobject
{
public:
virtual void show (void) = 0;
};
class base : public virtual object,
public virtual ibase
{
public:
base (int value) : object() { m_value = value; }
virtual ~base () {}
virtual void show (void) { std::cout << m_value << std::endl; }
private:
int m_value;
};
Now I have a hypothetical class, which does nothing more than store a number and prints it. It derives from object. So the 'diamond' is complete.
class derived1 : public virtual base
{
public:
derived1 (int value) : base (value) {}
virtual ~derived1 () {}
};
Now I derive from the base class. The thing to note about this derived class is that I have the same constructor parameters as the base class (int value).
class derived2 : public virtual derived1
{
public:
derived2 (void) : derived1 (15) {}
virtual ~derived2 () {}
};
Finally I derive from this derived class. However, note that this class does not have any constructor parameters. Instead, this class internally should know that the value should be 15 in this example.
My expectation is that when I instantiate derived2, it will construct derived1 with the value 15 and pass it through the object. I would hope to do the following:
derived1 works(1234);
derived2 doesNotWork;
works.show();
doesNotWork.show();
But when I attempt this, I get:
error C2512: 'base::base' : no appropriate default constructor available
If I add an empty base::base constructor then I end up having m_value undefined as I expected (but tried anyway)
I seem to be missing something obvious..., can someone highlight it?
Change the derived2 to this:
derived2(void) : derived1(15), base(15) {}
The same issue came-up here:
Why is Default constructor called in virtual inheritance?
And the answer is described in this FAQ:
http://www.parashift.com/c++-faq-lite/virtual-inheritance-ctors.html
In short: C++ does not call virtual constructors hierarchically. The most derived class is responsible for calling all the virtual base class constructors. So you must explicitly call derived1() and base() since they take parameters. The linked FAQ implies that the best practice here is to make the virtual base classes only have no-arg constructors.
You don't have diamond inheritance, there's no shared base classes here ( derived2 -> derived1 -> base -> ( object -> iobject ), ibase ), nowhere in this chain is there any duplicates. Hence, you don't need virtual inheritance, so just drop public virtual across the board. I realize this is a contrived example and doesn't match your real usage, but in my experience it's EXTREMELY rare that you actually need multiple inheritance with virtual calls, which is something which you generally should stay away from if at all possible ( object size, call overhead and general nastiness with how pointers behave ).
In C++ an interface can be implemented by a class whose methods are pure virtual.
Such a class could be part of a library to describe what methods an object should implement to be able to work with other classes in the library:
class Lib::IFoo
{
public:
virtual void method() = 0;
};
:
class Lib::Bar
{
public:
void stuff( Lib::IFoo & );
};
Now I want to to use class Lib::Bar, so I have to implement the IFoo interface.
For my purposes I need a whole of related classes so I would like to work with a base class that guarantees common behavior using the NVI idiom:
class FooBase : public IFoo // implement interface IFoo
{
public:
void method(); // calls methodImpl;
private:
virtual void methodImpl();
};
The non-virtual interface (NVI) idiom ought to deny derived classes the possibility of overriding the common behavior implemented in FooBase::method(), but since IFoo made it virtual it seems that all derived classes have the opportunity to override the FooBase::method().
If I want to use the NVI idiom, what are my options other than the pImpl idiom already suggested (thanks space-c0wb0y).
I think you've got your NVI pattern around the wrong way:
http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Non-Virtual_Interface
Not sure if that solves your issue though.
class IFoo
{
public:
void method() { methodImpl(); }
private:
virtual void methodImpl()=0;
};
class FooBase : public IFoo // implement interface IFoo
{
private:
virtual void methodImpl();
};
Here's an example of why you might do this using a reader that reads from XML and another from DB. Note that common structure is moved into the NVI readFromSource, while non-common behaviour is moved into the private virtual getRawDatum. This way logging and error checking is only needed in the one function.
class IReader
{
public:
// NVI
Datum readFromSource()
{
Datum datum = getRawDatum();
if( ! datum.isValid() ) throw ReaderError("Unable to get valid datum");
logger::log("Datum Read");
return datum;
}
private:
// Virtual Bits
Datum getRawDatum()=0;
};
class DBReader : public IReader
{
private:
Datum getRawDatum() { ... }
};
class XmlReader : public IReader
{
private:
Datum getRawDatum() { ... }
};
Commonly, the reason for using the NVI (sometimes also called "Template Method") is that derived classes should only change a part of the base class' behavior. So what you do is this:
class base {
public:
void f()
{
// do something derived classes shouldn't interfere with
vf();
// do something derived classes shouldn't interfere with
vg();
// do something derived classes shouldn't interfere with
vh();
// do something derived classes shouldn't interfere with
}
private:
virtual void vf(); // might be pure virtual, too
virtual void vg(); // might be pure virtual, too
virtual void vh(); // might be pure virtual, too
};
Derived classes can then plug into f() at the spots they are meant to and change aspects of f()'s behavior, without messing up its fundamental algorithm.
It may be confusing that once a method is declared as virtual in a base class, it automatically becomes virtual in all derived classes, even if the virtual keywords is not used there. So in your example, both methods of FooBase are virtual.
... to deny derived classes the
possibility of overriding the common
behavior implemented in
FooBase::method()...
If you can get rid of IFoo, and just start the hierarchy with FooBase with a non-virtual method, that would do it. But it looks like you want to allow direct children of IFoo to override method(), but to prevent children of FooBase to override it. I don't think that's possible.
You could use the pimpl-idiom to achieve this:
class IFoo
{
public:
IFoo( boost::shared_ptr< IFooImpl > pImpl )
: m_pImpl( pImpl )
{}
void method() { m_pImpl->method(); }
void otherMethod() { m_pImpl->otherMethod(); }
private:
boost::shared_ptr< IFooImpl > m_pImpl;
};
class IFooImpl
{
public:
void method();
virtual void otherMethod();
};
Now others can still subclass IFooImpl and pass it to IFoo, but they cannot override the behavior of method (they can override otherMethod). You can even make IFooImpl a direct subclass of IFoo and use enable_shared_from_this to initialize IFoo correctly. This is just the gist of the method. There are many ways to tweak this approach. For instance you can use the factory-pattern to make sure IFoos are created correctly.
Hope that helps.
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 { ... }
};