【问题标题】:How to enforce derived class members on derived classes如何在派生类上强制派生类成员
【发布时间】:2019-11-13 09:17:03
【问题描述】:

如何强制派生类具有特定派生类型的成员数据。

即,

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

我还可以存储指向项目的指针,然后将它们存储为正确的类型。是否有一种技术或设计模式可以对派生类的成员强制执行此类相应的继承规则?

【问题讨论】:

  • 您可以将 Employee 设为模板,并将项目子类型作为类型参数。或者保留 Employee 并有一个中间 EmployeeImpl 模板来自动进行转换。
  • 这是 OOP 中的大规模反模式。你为什么关心类存储什么data?具体来说,你想做什么,为什么不能是成员函数而不是成员变量?

标签: c++ oop inheritance design-patterns


【解决方案1】:

编译时的解决方案是使基础成为模板:

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

class Architect: public Employee<Building> {};

class Writer: public Employee<Article> {};

此外,您可以添加一个额外的非模板库,以便 ArchitectWriter 属于同一层次结构,但该非模板库无法处理 projs 成员。

如果模板不是一个选项,那么您必须依赖运行时检查。为此,Project 必须是多态类型,并且您必须使用typeiddynamic_cast 来强制执行不变量。您必须首先使用间接存储Projectstd::vector&lt;Project&gt; 不能存储任何 BuildingArticle 对象,因为它只存储 Project 对象

【讨论】:

【解决方案2】:

就像你提到的,你可以在基类中存储多态指针:

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());

【讨论】:

  • Project 必须至少有一个虚拟方法才能启用dynamic_cast
猜你喜欢
  • 2012-05-17
  • 1970-01-01
  • 2011-06-22
  • 2018-11-30
  • 1970-01-01
  • 2012-03-05
  • 2017-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多