用非纯虚拟版本重载纯虚拟功能

时间:2018-09-17 09:36:43

标签: c++

基本和派生定义如下:

class Base {

    public:
        virtual int f1(int a) const = 0;
        virtual int f2(int a, int b) const { return a+b;}
};

class Derived : public Base {

    public:
        int f1(int a) const { return a; }
}; 

int main() {
    Derived obj;
    cout << obj.f1(1) << endl;
    cout << obj.f2(1, 2) << endl;
}

结果是

1
3

obj.f1(1)使用来自 Derived obj.f2(1、2)的 f1 实现使用从 Base 继承的实现,这就是我想要的。

现在,我希望这两个函数具有相同的名称​​ f ,因此,当有两个参数且派生类必须实现单个参数版本时,基类将提供一个实现(即为什么它是纯虚拟的。)

但是,如果我这样做(只需将 f1 f2 重命名为 f ):

class Base {

    public:
        virtual int f(int a) const = 0;
        virtual int f(int a, int b) const { return a + b;}
};

class Derived : public Base {

    public:
        int f(int a) const { return a; }
};

int main() {
    Derived obj;
    cout << obj.f(1) << endl;
    cout << obj.f(1, 2) << endl;
}

我收到以下错误:

20:23: error: no matching function for call to 'Derived::f(int, int)'
20:23: note: candidate is:
14:13: note: virtual int Derived::f(int) const
14:13: note:   candidate expects 1 argument, 2 provided

这是为什么?这种重载不可能吗?

5 个答案:

答案 0 :(得分:10)

您需要写

class Derived : public Base {

    public:
        using Base::f;
        int f(int a) const { return a; }
};

请注意using语句。这将基类版本带回了范围。

答案 1 :(得分:8)

  

现在,我希望这两个函数具有相同的名称f

您需要写

class Derived : public Base {

    public:
        using Base::f;
        int f(int a) const { return a; }
};

请注意using语句。这将基类版本带回了范围。 [感谢@Bathsheba]

  

这是为什么?这种重载不可能吗?

否,由于[basic.scope.hiding¶3],不能像原始问题中所述那样写:

  

在成员函数定义中,在块处声明名称   范围隐藏具有相同成员的类的声明   名称;参见[basic.scope.class]。 成员的声明   派生类隐藏该类的基类成员的声明   相同的名称; 请参见[class.member.lookup]。

此子句与名称有关,而不是重载。因此,基类中是否有其他重载也没关系,它们都共享相同的名称 ,根据上面的引用将其隐藏。

答案 2 :(得分:1)

您可以通过编写Sub testarr() Dim arr As Variant, str As String, i As Integer str = "{test:[{test this here||Can it be split inside the array?}]}" arr = Split(str, "[{") For i = LBound(arr) To UBound(arr) arr(i) = Split(arr(i), "||") Next i End Sub 将Base的所有定义纳入范围,也可以为f的某些版本专门编写如下内容:using Base::f;

int f(int a, int b) const override {return Base::f(a,b);}

answer中已经提到了using的版本:

class Derived : public Base {

public:
    int f(int a) const { return a; }
    int f(int a, int b) const override {return Base::f(a,b);} 
};

注意:我知道第二个版本在MSVC 2010上不起作用。我也知道此编译器是古老的,但仅适用于关心的人;)

答案 3 :(得分:0)

除了其他解决方案之外,如果您不想重新定义f,则可以使用

显式调用基类的f
int main() {
    Derived obj;
    cout << obj.f1(1) << endl;
    cout << obj.Base::f2(1, 2) << endl;
}

答案 4 :(得分:-2)

您还可以使它们全部纯净,然后在派生类中覆盖它们。您可以继续使用自己的课程。