How to enforce derived class members on derived cl

2019-08-13 23:01发布

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?

2条回答
Root(大扎)
2楼-- · 2019-08-13 23:09

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());
查看更多
Animai°情兽
3楼-- · 2019-08-13 23:21

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

查看更多
登录 后发表回答