【问题标题】:C++ multiple inheritance method overloadingC++多继承方法重载
【发布时间】:2015-08-04 15:38:50
【问题描述】:
#include <iostream>

using namespace std;

class Base1 {
public:
    virtual void f(int n) = 0;
};

class Base2 {
public:
    virtual void f(char *s) = 0;
};

class Derive1 : public Base1, public Base2 {
public:
    void f(int n) { cout << "d1 fn" << endl; }
    void f(char *s) { cout << "d1 fs" << endl; }
};

class Derive2 : public Derive1 {
public:
    void f(int n) { cout << "d2 fn" << endl; }
    void f(char *s) { cout << "d2 fs" << endl; }
};

int main() {
    Derive1 *d1 = new Derive2();
    int n = 0;
    char *s = "";
    d1->f(n);
    d1->f(s);
    return 0;
}

上面的代码按预期运行,但是如果我注释掉Derive1的一个方法,就会出现转换错误;如果我注释掉 Derive1 的两种方法,我得到方法歧义错误。

让我感到困惑的是为什么 Derive1 必须定义这两个方法,为什么只在 Derive2 中定义它们不起作用。我需要一些帮助来理解这一点。

一些说明:

  1. 假设我不想创建任何 Derive1 实例。所以,如果 Derive1 是一个抽象类是完全可以的。

  2. “所有纯虚函数都应该在派生类中有定义。”如果我不想创建这个派生类的实例,这不是真的。

  3. 如果我将 Base1 中的 f 更改为 f1,将 Base2 中的 f 更改为 f2(只是更改名称),则 Derive1 不需要定义它们中的任何一个,只需在 Derive2 中定义 f1 和 f2 即可。

所以,在方法重载的支持下,我想,在上面的代码中,我在Base1中声明了一个名称为f_int的函数;在 Base2 中,我声明了一个名为 f_str 的函数。这就是编译器实现方法重载的方式,对吧?但似乎情况并非如此。

【问题讨论】:

    标签: c++ inheritance pure-virtual


    【解决方案1】:

    Derive1Base1Base2 的派生类。派生类必须实现其基类的所有虚函数。

    Derive2 实现这些函数对Derive1 没有帮助,因为可以实例化一个 Derive1,并且为此它必须实现所有继承的纯虚方法。

    例如,如果您没有实现Derive1 中的功能,您希望它的行为是什么?

    Derive1* d1 = new Derive1;
    int n = 0;
    char *s = "";
    d1->f(n);
    d1->f(s);
    

    Derive1 没有实现这些,d1 不是Derive2 实例,那么它应该做什么?

    【讨论】:

    • 派生类必须实现所有虚函数。
    • 谢谢,我已在我的帖子中添加了此说明。
    • 具体 类必须实现其基类中的所有纯虚方法。中间抽象类不需要。不过,在这种情况下,这不是问题。
    • 假设我不想创建任何 Derive1 的实例,我仍然需要定义 Derive1 继承的所有纯虚函数?
    【解决方案2】:

    如果你在一个类中声明一个纯虚函数,它会变成一个抽象类,你不能实例化那个。并且所有纯虚函数都应该在派生类中有定义。您的两个基类都具有纯虚函数,因此您的derived1 应该定义基类的纯虚函数。

    【讨论】:

      【解决方案3】:

      让我们从删除Derived1 中的两者开始:

      当您调用d1-&gt;f 时,您尚未创建任何特定于该类的内容,因此它会查看其基类。每个基类都将被视为一组单独的候选者。所以首先它检查 base1 并看到一个 f,然后检查 base2 并看到另一个 f。编译器无法选择调用哪一个,所以调用是模棱两可的。如果您不想重新实现父函数,可以将父函数using 转换为Derived1,或者提示编译器使用哪个基。

      如果你只注释掉Derived1 中的一个函数,你留下的那个隐藏两个父版本,防止其中一个被选中。此时你可以调用你定义的那个并且不能调用另一个,除非你再次告诉编译器你想从哪个特定的基类中调用它。

      【讨论】:

      • 在方法重载的支持下,我想在检查Base1时,编译器应该会看到类似f_int;检查 Base2 时,编译器应该看到类似 f_str 的内容。所以这两个 f 函数是两种不同的函数,那为什么一个会隐藏另一个呢?
      猜你喜欢
      • 2023-03-21
      • 1970-01-01
      • 2014-05-24
      • 2017-01-07
      • 2011-02-27
      • 1970-01-01
      • 1970-01-01
      • 2011-08-13
      • 1970-01-01
      相关资源
      最近更新 更多