Say you have a base class Dep for a tree of classes. There is a virtual method Dep* Dep::create() that I want to be implemented by every single leaf class. Is there any way to enforce this?
Note: The problem here is that there could be intermediate classes (say class B : public A : public Dep) implementing this method (A::create) by accident or because they think they are leaf classes, but are in fact subclassed themselves.
The question ends here.
Context
If you are curious why I need this; I have a class Master which has Dep objects of unknown concrete type. If Master is duplicated, I need to come up with a matching clone of the Dep instance. Next best thing to do is the virtual constructor idiom, which introduces precisely this problem.
Additionally, I cannot even catch this (other then by crashing horribly), because for obscure reasons, people that have more to say than me, have outlawed dynamic_cast in this project (perhaps this is a good decision; But anyways a completely different discussion).
C++ provides no way to keep a class from inheriting from your class, and there is no way to make a particular class in the inheritance hierarchy implement a method. The only rule is that somewhere in the inheritance hierarchy above a particular class (not necessarily in the leaf) all virtual functions must have an implementation for that class to be instantiatable.
For instance, A could inherit from Def and implement all it's [pure] virtual methods. Then if B inherits from A, it doesn't have to implement anything. There's no way to keep that from happening.
So the answer is no, there is no way to enforce this.
Using curiously recurring template fun, you can achieve something quite similar:
template<typename T>
class Cloneable : public T, public Dep
{
private:
Cloneable<T>() : T() { }
public:
static Cloneable<T>* Create() { return new Cloneable<T>(); }
Cloneable<T>* clone() { return new Cloneable<T>(*this); }
};
Instead of deriving from Dep and instantiating via new MyType, use Cloneable<MyType>::Create. Since Cloneable<MyType> is derived from MyType, you can use the instance the same way you would use any MyType, except that it is now guaranteed to have Dep::clone.
Additionally your Master should not accept an instance of type Dep, but enforce that it is a Cloneable<T>. (Replace your orignial function by a simple function template that enforces this.) This guarantees that any Dep inside the master has a correctly implemented clone function.
Since Cloneable<MyType> has no public constructor, it cannot be inherited, however your actual MyType can be further inherited and used just as before.
Did TPTB outlaw all RTTI, or only dynamic_cast<>()? If you can use RTTI, then you can enforce the existence of the method as a postcondition of calling it:
#include <typeinfo>
#include <cassert>
#include <iostream>
#include <stdexcept>
class Base {
protected:
virtual Base* do_create() = 0;
virtual ~Base() {}
public:
Base* create() {
Base *that = this->do_create();
if( typeid(*this) != typeid(*that) ) {
throw(std::logic_error(std::string() +
"Type: " +
typeid(*this).name() +
" != " +
typeid(*that).name()));
}
return that;
}
};
class Derive1 : public Base {
protected:
Base* do_create() { return new Derive1(*this); }
};
class Derive2 : public Derive1 {};
void f(Base*p) { std::cout << typeid(*p).name() << "\n"; }
int main() {
Derive1 d1;
Base *pD1 = d1.create(); // will succeed with correct semantics
Derive2 d2;
Base *pD2 = d2.create(); // will throw exception due to missing Derive2::do_create()
}
If you control the base class AbstractDep then you can enforce that concrete leaf classes must be created by using a class template WithCloning. This leaf can then be sealed so that it cannot be inherited. Or more precisely, instances cannot be created of a derived class.
class AbstractDep
{
template< class Type > friend class WithCloning;
private:
enum FooFoo {};
virtual FooFoo toBeImplementedByLeafClass() = 0;
public:
virtual AbstractDep* clone() const = 0;
};
template< class Type > class WithCloning;
class Sealed
{
template< class Type > friend class WithCloning;
private:
Sealed() {}
};
template< class Type >
class WithCloning
: public Type
, public virtual Sealed
{
private:
AbstractDep::FooFoo toBeImplementedByLeafClass()
{
return AbstractDep::FooFoo();
}
public:
virtual WithCloning* clone() const
{
return new WithCloning( *this );
}
};
typedef WithCloning<AbstractDep> Dep;
class AbstractDerivedDep
: public AbstractDep
{
// AbstractDep::FooFoo toBeImplementedByLeafClass(); // !Not compile.
public:
};
typedef WithCloning<AbstractDerivedDep> DDep;
struct Foo: Dep {}; // !Does not compile if instantiated.
int main()
{
Dep d;
//Foo f;
}
If the classes require more than default construction then that most be solved additionally.
One solution is then to forward an argument pack from the WithCloning constructor (there is an example C++98 implementation on my blog, and C++0x supports that directly).
Summing up, to be instantiable the class must be WithCloning.
Cheers & hth.,
when you say that they are unknown, i presume they still inherit from a common base class /interface right?
only thing i can think of you can use to force is on the virtual base class add
virtual Base* clone() {
assert( 1==0 ); //needs to be overriden
}
so you are forced to override, but this is only detected at run-time when trying to call clone on a instance of a class that is missing the override
even if you are not allowed to use dynamic_cast or RTTI, you can still enable it for debug purposes locally on your build, if that will help you find the typeid of offending classes
it sounds like you are familiar with the clone pattern, but i'll post it quietly in here, and we can forget about it:
http://www.cplusplus.com/forum/articles/18757/
Related
I usually try to find answers here before I post anything, but I'm not even sure how to formulate my question.
So here's what I want to do... I want to define a Base Interface, and a Derived Interface. Then, I want to implement the Base Interface, with extra variables and methods. Finally, I want to implemented a Derived class, from the implemented Base Interface BUT ALSO from the Derived Interface. I don't know about you, but my head hurts.
If I do something like below, I get Ambiguous definitions under the DerivedFloat code since that code "sees" both the GetBaseValue method from the IBase, inherited through IDerivedFloat, as well as the GetBaseValue inherited from Base.
Surely, there must be a way to derive a class which uses the expanded features of the Base Implementation, as well as making sure it implements the required IDerivedFloat methods.
Now... This is a dummy example to show what I'm conceptually trying to achieve. It's not a real life example.
template <typename VALUE_TYPE>
class IBase
{
public:
virtual VALUE_TYPE GetBaseValue() const = 0;
};
class IDerivedFloat : public IBase<FLOAT>
{
public:
virtual void SetBaseValue(const FLOAT & value) = 0;
};
// Implementation of Base
template <typename VALUE_TYPE>
class Base : public IBase<VALUE_TYPE>
{
public:
VALUE_TYPE GetBaseValue() const { return m_BaseValue; }
protected:
VALUE_TYPE m_BaseValue;
}
// Uses expanded Base AND implements IDerivedFloat
class DerivedFloat : public Base<FLOAT>, public IDerivedFloat
{
public:
void SetBaseValue(const FLOAT & value) { m_BaseValue = value };
}
You can use virtual inheritance to work around this problem:
class IDerivedFloat : virtual IBase<FLOAT>
{
public:
virtual void SetBaseValue(const FLOAT & value) = 0;
};
template <typename VALUE_TYPE>
class Base : virtual IBase<VALUE_TYPE>
{
public:
VALUE_TYPE GetBaseValue() const { return m_BaseValue; }
protected:
VALUE_TYPE m_BaseValue;
}
Using virtual inheritance gives the derive class one instance of the base class members, instead of one from each time it exists in the class hierarchy.
Multiple inheritance is an issue precisely because of the ambiguity issue you ran into, but there are ways to get around it. You have to explicitly tell the compiler which super you are calling the ambiguous functions from, by leading the function call with the super's name and a double colon.
Example:
- C inherits from A and B.
- A and B both have add() function.
- In C, you have to say A::add() or B::add() to tell the compiler which one to use.
Link for details and more complete implementation: http://www.cprogramming.com/tutorial/multiple_inheritance.html
I have the following base template class.
template<typename T>
class Base {
public:
void do_something() {
}
};
It is intended to be used as a curiously recurring template pattern. It should be inherited like class B : public Base<B>. It must not be inherited like class B : public Base<SomeoneElse>. I want to statically enforce this requirement. If someone uses this wrong, I expect an error in the compiling phase.
What I'm doing is putting a static_cast<T const&>(*this) in do_something(). This way the class inheriting the template is or inherits from the class provided as the template parameter. Sorry for the confusing expression. In plain English, it requires B is or inherits from SomeoneElse in class B : public Base<SomeoneElse>.
I don't know if it's the optimal way to achieve this. Looks gross to me.
However I want to do more. I want to ensure B is SomeoneElse itself. How can I do that?
Make the constructor (or destructor) of Base private, and then make T a friend. This way the only thing that can construct/destruct a Base<T> is a T.
If your class contains some code that says:
T* pT = 0;
Base *pB = pT;
Then there will be a compiler error if T is not assignment-compatible with Base.
This kind of check is formalised in C++11 so you don't have to write it by hand and can get helpful error messages:
#include <type_traits>
template<typename T>
class Base {
public:
void do_something()
{
static_assert(
std::is_base_of<Base, T>::value,
"T must be derived from Base");
}
};
class B : public Base<B> { };
int main()
{
B b;
b.do_something();
}
As to ensuring that Base's type parameter is exactly the class that is deriving from it, that seems conceptually flawed. A class that is acting as a base class can't "talk about" the type that is inheriting it. It may be inherited more than once via multiple inheritance, or not at all.
Two good answers so far. Here is another which uses the idiom of generating custom access keys to certain methods (in this case a constructor). It provides an absolute guarantee of correct use while not exposing private methods in the base to the derived.
It can also be used to control access to other methods in the base class on a case-by-case basis.
template<class Derived>
struct Base
{
private:
// make constructor private
Base() = default;
protected:
// This key is protected - so visible only to derived classes
class creation_key{
// declare as friend to the derived class
friend Derived;
// make constructor private - only the Derived may create a key
creation_key() = default;
};
// allow derived class to construct me with a key
Base(creation_key)
{}
// other methods available to the derived class go here
private:
// the rest of this class is private, even to the derived class
// (good encapsulation)
};
struct D1 : Base<D1>
{
// provide the key
D1()
: Base<D1>(creation_key())
{}
};
I have several derived classes (e.g. DerivedX, where x is derived class number) that differ in fields and member functions.
Than I want to extend each derived class with some set of properties (can be organised as a field Extension ex), preserving each DerivedX class. The latter means, that we could create "clear" DerivedX objects that would not contain the property Extension ex.
The derived objects are created in some code place (e.g., in function main()), than, if they possess an extended functionality, this functionality should be used (get,set, other methods are called from main()).
The first idea was to add this new property to every derived class forming new class (ExtendedX) for each of derived classes. But I feel the code would become bulky, it seems, this approach is bad:
class Base
{
protected:
int b;
...
}
class Derived1: public Base
{
protected:
int d1;
...
};
class Derived2: public Base
{
protected:
int d2;
...
}
...X classes defined
class Extended1: public Derived1
{
protected:
Extension ex;
public:
int getExProperty1(){return ex.getProperty1();} // the realization could differ: we could also return copy of Extension object, pointer, set every field separately or the whole Extension object
}
class Extended2: public Derived2
{
protected:
Extension ex;
public:
int getExProperty1(){return ex.getProperty1();} // the realization could differ: we could also return copy of Extension object, pointer, set every field separately or the whole Extension object
}
...X classes defined
The demanded functionality is repeated in each class in that case. It's highly deprecated practice.
The other (second) idea was to declare "class Extension" that would contain the property considered ("Extension ex" in the example) and create its objects on-demand along with the objects of classes DerivedX, when we need DerivedX objects to possess this property.
The third idea was to include pointer to Extension as a field to the Base class and simply initialize it to NULL when we don't want to use the extended functionality. But then, how can we call methods of Extension class from main()?
Extended functionality could also be different in the future (derived classes are extended in accordance with the kind of problem being solved), that's why the second and the third ideas are also better, than the first.
Is there any good solution to add pack of properties and functionality to multiple derived classes?
EDIT1:
I tried to implement mixin through CRTP, as suggested by Deduplicator.
However, the code fails with:
«class Base» has no member named «getProperty1»
«class Base» has no member named «setProperty1»
The code:
#include <iostream>
using namespace std;
class Base {
int a;
public:
virtual ~Base(){}
};
class Derived1: public Base
{
public:
virtual ~Derived1(){}
};
template <class T> class Extension: public T
{
int prop1;
public:
void setProperty1(int _p){prop1=_p;}
int getProperty1(){return prop1;}
};
int main()
{
Base* der = new Derived1();
Base* e = new Extension<Derived1>();
e->setProperty1(10);
cout<< e->getProperty1();
delete der;
delete e;
return 0;
}
Changing
e->
to
static_cast<Extension<Derived1> *>(e)->
makes the code working.
How to use Extension class objects right in this case?
Use the CRTP:
// Classes implementing additions
template<class T> class Extended : public T /*, potentially additional bases */ {
// Common extension here.
}
Another option, if you can redefine the various Derived classes but can't change the definition of Base, is to shove Extension into the class hierarchy between them and Base:
class Base
{ // ...
};
class Extension: public Base
{ // ...
};
class Derived1: public Extension
{ // ...
};
class Derived2: public Extension
{ // ...
};
This way, anything that doesn't need the new APIs in Extension can continue to use Base*, and the parts that need the new API can use Extension* (or dynamic_cast<Extension>(baseptr)) instead.
This assumes Extension needs access to Base. If it doesn't, then you can just implement Extension as a mixin:
class Base
{ // ...
};
class Extension
{ // ...
};
class Derived1: public Base, Extension
{ // ...
};
class Derived2: public Base, Extension
{ // ...
};
Composition or inheritance ?
when we need Derived objects to possess this property.
This sounds as if an object and its extended property have a "has-a" and not and "is-a" relationship. This would suggest composition rather than inheritance as solution.
"on demand" , "if we don't want" ...
These suggest an optional relationship. It sounds as if you'd decide at runtime and for each object if the extension is needed or not. This reinforces the preference for composition over inheritance.
To achieve this kind of behaviour with inheritance needs polymorphism, and you'd have to use pointers/references everytime you need to work with an object.
Extended functionality could also be different in the future (derived
classes are extended in accordance with the kind of problem being
solved),
In the future, could there be further derivation for the derived ? If yes, how would this further derivation relate to the extension ? If you'd say that further derivation would be independent of the extension, then composition should definitively be the choice.
Now which one of 2 and 3 to prefer ?
Looking at all the arguments above, the third option could be very interesting for both your current needs for a common extension, but also future needs.
Here is the general idea:
class Base {
...
protected:
Extension *ex;
void setExtension(Extension *e); // to be called by ctor or the derived.
public:
bool isExtended() { return ex!=nullptr; }
int getExProperty1(){ if (isExtend()) return ex->getProperty1();} // common member functions
};
But for this to remain extensible for future evolutions, Extension should define its member functions virtual. Then later some derived class could use a derivation of Extension:
class MyDerivedExtension : public Extension { // specially for Derived1 extensions
protected:
string myspecificproperty; // specific for Derived1
public:
int getPropery1 () { /* calculate it differently than for basic Extension */ }
string getProperty2 () { /*...*/ } // specific to Derived1
};
class Derived1: public Base
{
...
protected:
void setExtension(MyDerivedExtension *e) { Base::setExtension(e); } // to be called by ctor.
public:
string getExProperty2(){ if (isExtend()) return ex->getProperty2();} // non common member
};
I have a base class with a bunch of functionality and a derived class that extends that class but there are a few methods in the base class that don't make sense on the derived class.
Is it possible to do something to prevent these method(s) from being used by the derived class?
Class A
{
...
public:
void SharedMethod();
virtual void OnlyMakesSenseOnA();
}
Class B : public Class A
{
...
public:
void OnlyMakesSenseOnB();
}
The following obviously doesn't work but is it possible to do something similar so that the compiler doesn't allow a certain base class method to be called?
Class B : public Class A
{
...
public:
void OnlyMakesSenseOnA() = 0;
}
No, and this is completely wrong. If the member function is not callable in the derived type you are breaking the Liskov Substitution Principle. Consider whether this is the correct inheritance relationship. Maybe you want to extract SharedMethod to a real base and provide two separate unrelated A and B types.
This isn't as easy of an answer as I had hoped, but a coworker suggested that this situation is an indication of bad design and that I should re-think my inheritance structure by adding a new base class that only contains common functionality:
Class Base
{
...
public:
void SharedMethod();
}
Class A : public Base
{
...
public:
void OnlyMakesSenseOnA();
}
Class B : public Base
{
...
public:
void OnlyMakesSenseOnB();
}
Edit: Thanks to #David for providing a name for the rule that I'm trying to break. B is not a "Behavioural Subtype" of A because it fails the "counterfeit test". Therefore, deriving B from A violates the Liskov Subtitution Principle.
According to this slide deck, the counterfeit test is as follows:
Suppose I promise to deliver you an object of class T, but
instead I give you an object x of class S.
You can subject x to any series of method calls you like
(chosen from T’s signature).
If x behaves in a way that is not expected of a T object,
then you know it is a counterfeit, x has failed the test.
If all S objects always pass every counterfeit test, then S is
a behavioural subtype of T.
You could also just throw an exception if the invalid method is called on the derived class. It doesn't catch the bug at compile time but at least it prevents it from accidentally being used a runtime.
Class B : public Base
{
...
public:
void OnlyMakesSenseOnA() { throw Exception(); }
}
Yes, it's possible and quite simple, if we're talking about an external call. You can hide parent's method with private methods of derived class. Works with the static methods as well.
Tested on cpp 98, 11, 14. Try yourself in C++ shell.
class Base{
public:
void methodBase(){};
static void methodBaseStatic(){};
};
class Derived : public Base{
//private: //(private on default)
void methodBase(){};
static void methodBaseStatic(){};
};
Normal operation:
int main()
{
Base b;
b.methodBase();
Base::methodBaseStatic();
Derived d;
return 0;
}
Compilation error
int main()
{
Derived d;
d.methodBase();
Derived::methodBaseStatic();
return 0;
}
How do you design polymorphism when you have a member which type depends on some constraints.
Say I have this :
template<typename T>
class Base
{
public:
Base() = default;
virtual ~Base() = default;
T member;
};
class DerivedA : public Base<int>
{
public:
DerivedA() {member = 5;}
};
class DerivedB : public Base<float>
{
public:
DerivedB() = default;
};
I want to be able to create a new derived object depending on different parameters, i.e :
Base *b;
if (something)
b = new DerivedA();
else
b = new DerivedB();
Obviously I can't do this since I need to provide template parameters for the declaration of b.
Is this bad design ? How do you handle this ?
I could write a small wrapper :
class Wrapper() {};
template<typename T>
class Base : public Wrapper
{
// ...
};
Wrapper a, b;
a = new DerivedA;
b = new DerivedB;
But then I won't have access directly to member or other methods declared in Base or Derived. I would need to cast : reinterpret_cast<DerivedA*>(a)->member, making polymorphism useless.
Thanks
Wrapper design should be exactly what you are looking for. The problem is that c++ is statically typed, so you can't declare member without specifying its type. The common way to avoid this is to design a base class which supports all the functionality you want, and implement a specific behaviour in derived classes, just as you did.
Probably the problem is that your class doesn't support all the functionality you need. Try to avoid using member directly and wrap its usage into virtual methods. Reimplement these methods in your derived classes.
If this is still not an option, consider methods for extracting your member. Maybe virtual getters and setters with appropriate conversions.
As a last resort, consider boost::variant, boost::any. But really they are implemented using the technique similar to your wrapper. So you get wrapper for the wrapper.
Well, if the "access" depends on the template parameter T (such reading Base.member), then you have to supply it somehow. Casting to one of the derived classes is one way to do it, but you don't need the reinterpret_cast. You need to start using pointers/references, to avoid the cut-off and let the substitutability work correctly:
Wrapper *a, *b;
a = new DerivedA;
b = new DerivedB;
int a_member = static_cast<DerivedA*>(a)->member;
float b_member = static_cast<DerivedB*>(b)->member;
And if you add a virtual method to Wrapper to make it polymorphic, you can do dynamic cast as well:
DerivedB* b_derived = dynamic_cast<DerivedB*>(b);
if (b_derived != nullptr) {
float b_member = b_derived->member;
// ...
}