我可以在继承中只覆盖一种方法吗?

Posted

技术标签:

【中文标题】我可以在继承中只覆盖一种方法吗?【英文标题】:Can I override only one method in inheritence? 【发布时间】:2013-03-16 15:25:30 【问题描述】:

我的C++代码如下:

#include<iostream>
using namespace std;

class A

    public:
        virtual void f(int i)
        
            cout << "A's f(int)!" << endl;
        
        void f(int i, int j)
        
            cout << "A's f(int, int)!" << endl;
        
;

class B : public A

    public:
        virtual void f(int i)
        
            cout << "B's f(int)!" << endl;
        
;

int main()

    B b;
    b.f(1,2);
    return 0;

在编译期间我得到:

g++ -std=c++11 file.cpp 
file.cpp: In function ‘int main()’:
file.cpp:29:9: error: no matching function for call to ‘B::f(int, int)’
file.cpp:29:9: note: candidate is:
file.cpp:20:16: note: virtual void B::f(int)
file.cpp:20:16: note:   candidate expects 1 argument, 2 provided

当我尝试在 B 的 f(int) 之后使用 override 时,我得到了同样的错误。

是否可以在 C++ 中仅覆盖 1 种方法?我一直在寻找一个使用override 的代码示例,它可以在我的机器上编译,但还没有找到。

【问题讨论】:

Virtual method causes compilation error in Derived class的可能重复 不,抱歉,这是另一个问题。 C++: rationale behind hiding rule的可能重复 【参考方案1】:

问题是您在类B 中的虚函数f() 隐藏 A 具有相同名称的非虚重载。您可以使用using 声明将其纳入范围:

class B : public A

    public:
        using A::f;
    //  ^^^^^^^^^^^

        virtual void f(int i)
        
            cout << "B's f(int)!" << endl;
        
;

【讨论】:

【参考方案2】:

您将名称“f”覆盖为方法名称。因此,任何重载也将被覆盖。

您可以使用using 关键字,只是告诉编译器也要查看基类:

class B : public A

    public:
        using A::f;
        virtual void f(int i)
        
            cout << "B's f(int)!" << endl;
        
;

【讨论】:

【参考方案3】:

您被 C++ 中名称查找的工作方式所困扰。编译器搜索连续的作用域,直到找到一个作用域,其中至少有一个具有匹配名称的项。

假设 item 是一个函数,然后它会在它在该范围内找到的具有该名称的函数之间进行重载解析。如果这些都不起作用,它确实不会继续搜索更多范围以找到更合适的。

但是,在这种情况下,您可以让它搜索父类:

class B : public A

    public:
        using A::f;
        virtual void f(int i)
        
            cout << "B's f(int)!" << endl;
        
;

乍一看,using 语句可能会产生歧义。例如,对于using A::f;,现在有两个 f(int) 函数在B 的范围内可见(A::f(int)B::f(int))。 C++ 也有一些规则来涵盖这一点,所以如果你在main 中添加(例如)b.f(3);(使用using A::f;),你仍然不会有歧义——它会调用b::f(int)如你所料。

【讨论】:

【参考方案4】:

派生类中定义的函数f隐藏了名为f的基类函数。 要将隐藏函数带入派生类范围,您需要添加:

using A::f;

到你的基类定义。

好读:

What's the meaning of, Warning: Derived::f(char) hides Base::f(double)?

【讨论】:

【参考方案5】:

是的,可以只覆盖一个类的一个方法,使其成为虚拟方法。在继承类中声明时,非 virtual 将被遮蔽。

【讨论】:

以上是关于我可以在继承中只覆盖一种方法吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何继承继承的方法而不是覆盖继承的方法?

PHP 知识点

覆盖和重载 Java

将要覆盖的实现方法分开是pythonic吗?

java中父类的方法已经被覆盖那子类还能用super关键字调用父类的方法吗

我应该将所有方法标记为虚拟吗?