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;
// ...
}
Related
Looking for: accessing member of a derived class from a pointer to base.
Reductio ad absurdum:
class Base
{
public:
int member_of_base;
};
class Derived : public Base
{
public:
int member_of_derived;
};
I'm currently using templates:
template <class T>
class Client
{
T* data; // T is Base or Derived
};
There are few levels of composition in the class hierarchy, so I have to carry the template type parameter through all of the hierarchy. What is the best approach to overcome this?
Obviously I cannot access the member of Derived via a pointer to Base, i.e:
Base* foo = new Derived();
foo->member_of_derived; // no go
Thus, I'm using:
Client<Base>
Client<Derived>
I'm trying to come up with a solution that works without the templates. Options that I know would work:
void* //plain old C and casting as necessary, they're all pointers
(as in memory addresses) in the machine
static_cast<Derived*>(pointer_to_base); //type safe at compile time.
wrapping the cast in a Client's template method (not to be confused with a design pattern here)
The last option seems to be the most "elegant", i.e:
template <class T>
T* get_data() const { return static_cast<T*>(data); }
However, looking here and there tells me there might exist a way unknown to me.
I saw CRTP, but that brings me back to templates, which is the original thing I want to go without.
What are the ways, or popular approaches, to achieve such a goal?
The real code uses shared_ptr, weak_ptr and enable_shared_from_this with weak_from_this. I'm looking for a type safe "polymorphic member" access.
EDIT: they're not just "ints". They can be totally different types, as in protobuf in base and Json::Value in derived. And I'm trying to use the pointers to Base/Derived, which in turn would give me access to their respective members.
A virtual getter can solve the issue for you; as data types differ, you might pack them into a std::variant.
class Base
{
// having private members probably is more appropriate
int member_of_base;
public:
using Data = std::variant<int, double>;
virtual ~Base() { } // virtual functions -> have a virtual destructor!
virtual Data getMember() // or just "member", if you prefer without prefix
{
return member_of_base;
}
};
class Derived : public Base
{
double member_of_derived;
public:
Data getMember() override
{
return member_of_derived;
}
};
std::unique_ptr<Base> foo = new Base();
foo->getMember(); // member_of_base;
std::unique_ptr<Base> bar = new Derived();
bar->getMember(); // member_of_derived;
Admitted, not yet totally without templates, std::variant is one, but I suppose in that form it is acceptable...
There are some issues with, though:
Accessing the value is not the simplest, you might consider visit function for.
More severe: Base class (or wherever else you define the variant to be used) needs to be aware of all types that might be in use, adding a new type will force to recompile all other classes.
It has the smell of bad design. Why should it be necessary for a derived class to return something different than the base that shall serve the same purpose, though???
If you can delegate the work to be done to the classes themselves, you get around all these problems:
class Base
{
int member_of_base;
public:
virtual ~Base() { }
virtual void doSomething()
{
/* use member_of_base */
}
};
class Derived : public Base
{
double member_of_derived;
public:
void doSomething() override
{
/* use member_of_derived */
}
};
The latter would be the true polymorphic approach and normally the way to go; whereas the sample above returns void, you might just do all the calculations necessary in base and derived classes until you finally get to some common data type and return this one. Example:
class Base
{
int64_t m_balance; // in 100th of currency in use
public:
virtual ~Base() { }
virtual int64_t balance()
{
return m_balance;
}
};
class Derived : public Base
{
long double m_balance; // arbitrary values in whole currency entities
public:
int64_t balance() override
{
// calculate 100th of currency, correctly rounded:
return std::llround(m_balance * 100);
}
};
Admitted, I doubt pretty much representing a balance in double (even if long) is a good idea (issues with rounding, precision, etc)...
How can I get derived class object from my generic interface pointer.
I do not want to type cast the generic interface in order to achieve above .
e.g:
class Base {}; // Has pure virtual functions and is my interface class
class Derived : public Base {}; // Additional functions .
Base *b = new Derived();
Now, I want to get derived pointer Derived *derived from b without casting.
How can I achieve this?
Your setup seems strange, I'd look for alternative options like returning Derived directly or moving the functions you need into base since you seem to need them.
If you still want to do that you could have something like:
class Derived; // Forward declaration
class Base {
public:
virtual Derived* as_derived() { return null; }
...
};
class Derived : public Base {
public:
Derived* as_derived() override { return this; }
};
Still, this looks like a hack and I would suggest casting instead. At least casting it's a common pattern and it will be easier for others to understand.
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; }
};
Is it an O.K. design if i return an instance of Derived class from Base class member function(created using new Derived()) ?
Also this involves the need to forward declare the Derived class and also make the Derived class constructor public.
Code Sample :-
Class Base
{
public:
Base() {}
Derived* get_new_derived(int X)
{
Derived *der = new Derived(X);
return der;
}
}
Class Derived : public Base
{
private:
int _X;
protected:
Derived(int X) { _X = X; }
public:
Derived* get_new_derived(int X)
{
Derived *der = new Derived(X);
return der;
}
}
I have one more derived class(say Derived1). Now let's say :-
Usage1 :
Derived1* der1 = new Derived1();
Derived * der = der1->get_new_derived(10);
Usage2 :
Derived1* der1 = new Derived1();
Base* bs = der1;
Derived * der = bs->get_new_derived(10);
In the general case, this usually indicates bad design - a base class shouldn't normally know/care about its derived classes.
Note that you can return a pointer to Derived typed as Base* - that's the principle of the Factory Method design pattern. Perhaps this fits your actual scenario?
Note however that all rules have exceptions. If your (base class + derived classes) represent a tighly coupled and coherent unit (such as a Tree interface with two subclasses FastTree and SmallTree, optimised for different purposes), it is acceptable for them to be aware of each other, and Tree defining such functions as:
std::unique_ptr<SmallTree> Tree::createSmallCopy() const
{
return { new SmallTree(/*args*/) };
}
std::unique_ptr<FastTree> Tree::createFastCopy() const
{
return { new FastTree(/*args*/) };
}
So it depends on your actual use case. I'd generally be wary of such design, it but it has its uses.
As a side note, in modern C++, you should never use an owning raw pointer - use a smart pointer like std::unique_ptr or boost::shared_ptr.
How about this?
// The Curiously Recurring Template Pattern (CRTP)
template<class Derived>
class Base
{
// methods within Base can use template to access members of Derived
};
class Derived : public Base<Derived>
{
// ...
};
http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
Yes you can do it. The question is whether you should.
You shouldn't do it since it implies Base knows Derived which isn't proper object oriented design. The dependencies should be one way - derived knows the Base and not vice versa.
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/