How does one enforce a derived class to have member data of a specific derived type.
i.e.,
class Project {
public:
int projdata;
};
class Article: public Project {
};
class Building: public Project {
};
class Emplooyee {
public:
std::vector<Project> projs;
}
class Architect: public Employee {
};
class Writer: public Employee {
};
How do I now enforce that Architect objects only have projects of type Building, while Novelist only have projects of type Article? i.e., I want to have something like
class Architect: public Employee {
public:
std::vector<Building> projs;
};
and
class Novelist: public Employee {
public:
std::vector<Article> projs;
};
I could also store pointers to projects and then store cast them into the correct type. Is there a technique or design pattern to enforce such corresponding inheritance rules on members of derived classes?
A compile time solution is to make the base a template:
template<class Proj>
class Emplooyee {
public:
std::vector<Proj> projs;
}
class Architect: public Employee<Building> {};
class Writer: public Employee<Article> {};
Additionally, you can add a one additional non-template base so that Architect and Writer are part of same hierarchy, but that non-template base cannot deal with the projs member.
If a template not an option, then you must rely on runtime checks. For that, Project must be a polymorphic type, and you must use typeid or dynamic_cast, to enforce the invariant. And you must use indirection to store the Project's in the first place. std::vector<Project> cannot store any Building nor Article objects because it only stores Project objects only
Like you mentioned, you could store polymorphic pointers in the base class:
class Employee {
public:
std::vector<Project*> projs;
}
And use dynamic_cast to downcast them:
dynamic_cast<Building*>(projs[i])->doSomething();
But I wouldn't recommend this approach(unless necessary) since this will require you to manage the memory behind those pointers. (Which of course can be off-loaded to std::unique_ptr for example.)
Unless you require the Employee to be a polymorphic class, far simpler approach would be to use a class template
template <typename T>
class Employee {
public:
std::vector<T> projs;
}
which can be used like so:
class Architect : public Employee<Building> {
};
Architect architect;
architect.projs.push_back(Building());
Related
Assuming I just created a class named Base with 2 or 3 Members, that's about this:
class Base
{
private:
std::string name;
std::string number;
public:
virtual std::string get() const;
virtual void set();
//...
};
And in the next step I want to create a few derived classes form this class. But in some of the derived classes I don't need all members of the Base class.
How can I exclude some members of Base-class in a derived class and keep the others?
For Instance in:
class Derived_One : public Base {
private:
std::string wight;
int A;
public:
//...
};
I want to keep only the first attribute of the Base Class (std::string name) and remove the second attribute which is std::string number. How can I exclude it in the derived class Drive_One?
I am looking for an elegant solution for this change or a widely known Design Pattern which I do not know yet.
If your derived class only needs some of the base class, it is a sign that the base class should be split into two. Either one class derived from the other or two separate classes.
An example of the first case could be something like this:
class Base_One
{
private:
std::string name;
public:
//...
};
class Base_Two : public Base_One
{
private:
std::string number;
public:
//...
};
class Derived_One : public Base_One
{
private:
std::string wight;
int A;
public:
//...
};
class Derived_Two : public Base_Two
...
In the second case (if it does not make sense for Base_Two to derive from Base_One), Base_One and Base_Two would be separate classes and derived classes would derive from one or both of them, i.e. the example above would be modified as follows:
class Base_Two
{
private:
std::string number;
public:
//...
};
...
class Derived_Two : public Base_One, public Base_Two
...
derived classes I don't need all members of the Base class.
Which simply says: This is not a common base class!
Whats to do:
Option 1)
Split base class to several ones and create a linear hierarchy structure.
But this may come to a point, where your design would be to complex, especially if it feels natural to cross call from different members of different classes in the hierarchy.
Option 2)
If your design becomes more complex by simply splitting to linear hierarchy, you should give CRTP a chance.
This enables to inject special functionality into a class hierarchy and keeps the design cleaner. The bad side is, that this may lead to a lot of template instances which waste memory. You have a more maintainable design but you may pay with higher memory consumption.
What is the best for your design can't be answered on the fly from some lines of code. Simply try to understand both options and take a decision. Maybe you will change it later.
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 set of abstract parent classes in a namespace, similar to the following
namespace Core {
class Sparse;
class Dense;
}
I define those classes somewhere and after that I derive some child classes:
class SparseA: public Core::Sparse;
class SparseB: public Core::Sparse;
class DenseA: public Core::Dense;
Now I want to instantiate some objects of the child classes and store them in a common container that can be accessible from anywhere. How can I do this?
And another question: Should I include the child classes in the Core namespace aswell?
Thank you.
As long classes Sparse and Dense are unrelated, you can't store instances of derived classes in the same c++ standard container (unless you're going to use such fancy stuff as boost::variant or boost::any).
If you give them a common (abstract) base class you can use smart pointers ( e.g. std::unique_ptr<> or std::shared_ptr) to keep referencing them in a container (using the same pseudo syntax as in your sample)
namespace Core {
class CommonBase;
class Sparse : public CommonBase;
class Dense : public CommonBase;
}
typedef std::vector<std::unique_ptr<Core::CommonBase>> MyContainerType;
Another option might be a template wrapper class solution
namespace Core {
class WrapperBase {
public:
// Expose the common interface of Sparse and Dense as
// pure virtual functions
virtual void foo() = 0;
virtual ~WrapperBase() {}
};
template<class Impl>
class Wrapper : public WrapperBase {
private:
Impl& impl_;
public:
Wrapper(Impl& impl) : impl_(impl) {}
void foo() {
impl.foo(); // Delegate to the actual implementation
}
};
class Sparse;
class Dense;
}
typedef std::vector<std::unique_ptr<Core::WrapperBase>> MyContainerType;
MyContainerType container;
container.push_back(std::make_unique<Wrapper<SparseA>>());
container.push_back(std::make_unique<Wrapper<SparseB>>());
container.push_back(std::make_unique<Wrapper<DenseA>>());
The latter will allow to loosely couple classes like Sparse and Dense within a single container, but still at least requires some abstract interface, that could be be used behaviorally consistent for both classes, and classes derived from them.
Found related questions but not the exact variant so I am posting a very simple question.
A derived class inherits from a templated base, and I want to call the base function, how to do it?
template <class A>
class testBase {
public:
void insert(const A& insertType) {
// whatever
}
};
class testDerived : testBase<double> {
// whatever
};
int main() {
testDerived B;
// Compiler doesn't recognize base class insert
// How do you do this?
B.insert(1.0);
}
Need public inheritance (default is private for class):
class testDerived : public testBase<double> {
A class has a default access level of 'private'. You basically inherited 'testBase' using private inheritance so that testBase's public interface is not part of testDerived's. Simple solution:
class testDerived: public testBase<double> {...};
I do wish C++ applied public inheritance by default though since that's generally a much more common case. Then again, we could just all use structs instead. :-D