Как применять производные члены класса к производным классам - PullRequest
0 голосов
/ 02 июля 2019

Как заставить производный класс иметь данные-члены определенного производного типа.

т.е.,

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 {
};

Как мне теперь обеспечить, чтобы у объектов Architect были только проекты типа Building, в то время как у Novelist есть только проекты типа Article? я хочу иметь что-то вроде

class Architect: public Employee {
  public:
    std::vector<Building> projs;
};

и

class Novelist: public Employee {
  public:
    std::vector<Article> projs;
};

Я мог бы также хранить указатели на проекты, а затем сохранять их в правильном типе. Существует ли методика или шаблон проектирования для обеспечения соблюдения таких соответствующих правил наследования для членов производных классов?

Ответы [ 2 ]

2 голосов
/ 02 июля 2019

Решение времени компиляции - сделать базу шаблоном:

template<class Proj>
class Emplooyee {
  public:
    std::vector<Proj> projs;
}

class Architect: public Employee<Building> {};

class Writer: public Employee<Article> {};

Кроме того, вы можете добавить еще одну базу без шаблонов, чтобы Architect и Writer были частью одной иерархии, но эта база без шаблонов не может иметь дело с projs членом.

Если шаблон не вариант, то вы должны полагаться на проверки во время выполнения. Для этого Project должен быть полиморфным типом, и вы должны использовать typeid или dynamic_cast, чтобы применить инвариант. И вы должны использовать косвенное обращение, чтобы хранить Project в первую очередь. std::vector<Project> не может хранить ни Building, ни Article объектов, поскольку он хранит только Project только объекты

0 голосов
/ 02 июля 2019

Как вы упомянули, вы можете хранить полиморфные указатели в базовом классе:

class Employee {
  public:
    std::vector<Project*> projs;
}

и использовать dynamic_cast, чтобы понизить их:

dynamic_cast<Building*>(projs[i])->doSomething();

Но я бы не рекомендовалэтот подход (если не требуется), так как это потребует от вас управления памятью за этими указателями.(Который, конечно, может быть выгружен, например, до std::unique_ptr.)

Если вы не хотите, чтобы Employee был полиморфным классом, гораздо более простой подход состоял бы в использовании шаблона класса

template <typename T>
class Employee {
public:
    std::vector<T> projs;
}

, который можно использовать так:

class Architect : public Employee<Building> {
};

Architect architect;
architect.projs.push_back(Building());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...