【问题标题】:Override pure virtual function with different parameter of derived type用不同的派生类型参数覆盖纯虚函数
【发布时间】:2020-05-07 10:04:51
【问题描述】:

关于这个主题有很多问题,但是,我没有找到以下问题的解决方案:

我有以下课程:

1) 纯虚类

class Employee {
private:
    vector<Employee> vec_employee;

public:
    Employee() {};
    virtual ~Employee() {};
    virtual void set_vec_subordinate(vector<Employee> vec_employee) = 0;
};

2) 派生类

class Worker : Employee{ private: public: };

3) 另一个派生类,它应该覆盖来自 Employee 的纯虚方法

class Manager : Employee {
private:
public:
    inline void set_vec_subordinate(vector<Worker> vec_employee) override { this->set_vec_subordinate(vec_employee); };
};

我试图实现的是覆盖纯虚方法,但使用“不同”参数。所以对 C++ 来说还是新手,但我认为应该有办法这样做,特别是因为 另一个参数来自 Worker 类型,它是 Employee 的派生类

【问题讨论】:

  • 即使 C++ 允许逆变并将其应用于向量,您的方法也不是逆变变。你不会支持vector&lt;Manager&gt;(而Employee会)。
  • C++ 仅支持来自指针/引用的返回类型的协变。 (我们不能添加协方差关系(例如智能指针))。
  • 术语:具有一个或多个纯虚函数的类是抽象类。没有“纯虚拟类”这样的东西。

标签: c++ overriding derived


【解决方案1】:

没有办法完全按照你的计划去做(这是有充分理由的)。

您的代码本身也被破坏了,因为您使用类型 vector&lt;Employee&gt;,它需要类型为 Employee 的对象 - 因为 Employee 是一个抽象类,所以它不存在。您可能希望使用引用类型的vector,例如vector&lt;shared_ptr&lt;Employee&gt;&gt;。 (这个答案的其余部分掩盖了这一事实,使其更具可读性。)

另请注意,void Manager::set_vec_subordinate(vector&lt;Worker&gt; vec_employee) override { this-&gt;set_vec_subordinate(vec_employee); }; 在调用时会导致无限循环(可能导致堆栈溢出),因为它只会继续调用自己。

Employee 类与其用户签订了合同,规定以下代码必须有效(假设给定 get_bossget_workers 函数):

Employee& boss = get_boss();
vector<Employee> subordinate_vec = get_workers();
boss.set_vec_subordinate(subordinate_vec);

现在,这可能对您的应用程序没有任何语义意义,但编程语言的语法意味着这必须是可能的。一些编程语言(不是 C++!)允许与此类似的协变调用:

Employee& boss = get_boss();
vector<Worker> subordinate_vec = get_workers();
boss.set_vec_subordinate(subordinate_vec);  // Invalid C++: `vector<Worker` cannot be converted to `vector<Employee>` implicitly

虽然确实可以在 C++ 中创建一个容器,它的行为方式使得这种使用成为可能,但更容易处理它是通过将 set_vec_subordinate 函数设为需要任意对象容器的模板可以隐式转换或从Employee 派生 - 然后在复制操作期间转换对象(因为在这种情况下向量无论如何都不能移动)。

第二个想法是在重写函数时应该可以更改函数的签名。这在 C++ 中是可能的,方法是实现基本情况(它需要与二进制兼容 - 又名等于 - Employee 版本的签名,因为它也会被调用)然后添加额外的重载.例如,您可以执行以下操作:

class Manager : Employee {
private:
public:
    inline void set_vec_subordinate(vector<Employee> vec_employee) override { this->vec_employee = std::move(vec_employee); };
    inline void set_vec_subordinate(vector<Worker> const& vec_worker) {
        vec_employee = std::vector<Employee>(vec_worker.begin(), vec_worker.end());  // copy convert all elements
    };
};

【讨论】:

  • 感谢您提供这个非常好的答案。这有助于我更好地理解 C++,并有望提高我的编程技能。
猜你喜欢
  • 2020-08-01
  • 2013-09-11
  • 1970-01-01
  • 2011-02-24
  • 2018-12-23
  • 2013-10-04
  • 2021-09-30
  • 2022-01-13
  • 1970-01-01
相关资源
最近更新 更多