Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 虚拟函数和默认参数_C++_Overriding - Fatal编程技术网

C++ 虚拟函数和默认参数

C++ 虚拟函数和默认参数,c++,overriding,C++,Overriding,假设我有a、B和C级 class A{ public: virtual void f4(){ cerr<<"A::f4()"<<endl; } }; class B: public A{ public: virtual void f4(int n){ cerr<<"B::f4("<<n<<")"<<endl;

假设我有a、B和C级

class A{
    public:
        virtual void f4(){
            cerr<<"A::f4()"<<endl;
        }
};


class B: public A{
    public: 
        virtual void f4(int n){
            cerr<<"B::f4("<<n<<")"<<endl;
        }
};

class C: public B{
    public:
        virtual void f4(int n = 1){
            cerr<<"C::f4("<<n<<")"<<endl;
        }
};

我原以为会调用c版本的f4,但事实并非如此。有人能解释一下吗

因为f4的签名在A和B/C类之间不匹配

这是A的f4功能签名:

void A::f4()  // no parameters
B和C使用此函数签名

void B::f4(int n)
如果要重写方法,则它需要具有相同的返回类型和相同的参数列表。否则,即使派生类中的方法与父类相同的名称,C++也不会考虑重写。 FWIW,
C::f4
确实覆盖了
B::f4
。在
类C
上引入的默认参数不会影响虚拟方法重写行为。这就是为什么在我的团队中,我们不允许使用不同签名的重载方法,也不允许使用默认参数的确切原因。因为它会导致这样的错误

这是C的v表(表中提供的方法):


因为f4的签名在A和B/C类之间不匹配

这是A的f4功能签名:

void A::f4()  // no parameters
B和C使用此函数签名

void B::f4(int n)
如果要重写方法,则它需要具有相同的返回类型和相同的参数列表。否则,即使派生类中的方法与父类相同的名称,C++也不会考虑重写。 FWIW,
C::f4
确实覆盖了
B::f4
。在
类C
上引入的默认参数不会影响虚拟方法重写行为。这就是为什么在我的团队中,我们不允许使用不同签名的重载方法,也不允许使用默认参数的确切原因。因为它会导致这样的错误

这是C的v表(表中提供的方法):

出现以下警告:

main.cpp:14:22: warning: 'B::f4' hides overloaded virtual function [-Woverloaded-virtual]
    virtual void f4(int n){
                 ^
main.cpp:6:22: note: hidden overloaded virtual function 'A::f4' declared here: different number of parameters (0 vs 1)
    virtual void f4(){
                 ^
这些警告说明了发生了什么。虚拟函数仅由具有相同签名的另一个函数重写

B::f4(int)
不会覆盖
A::f4()
,因为它们有不同的参数列表。相反,它是一个不同的虚拟函数

因此,
rac.f4()
只调用未被覆盖的
A::f4()

由于C++11,您可以帮助检测此问题:

virtual void f4(int n) override {
//                     ^^^^^^^^
如果此函数实际上没有重写基函数中的某些内容,则编译器将给出错误。

编译时会出现以下警告:

main.cpp:14:22: warning: 'B::f4' hides overloaded virtual function [-Woverloaded-virtual]
    virtual void f4(int n){
                 ^
main.cpp:6:22: note: hidden overloaded virtual function 'A::f4' declared here: different number of parameters (0 vs 1)
    virtual void f4(){
                 ^
这些警告说明了发生了什么。虚拟函数仅由具有相同签名的另一个函数重写

B::f4(int)
不会覆盖
A::f4()
,因为它们有不同的参数列表。相反,它是一个不同的虚拟函数

因此,
rac.f4()
只调用未被覆盖的
A::f4()

由于C++11,您可以帮助检测此问题:

virtual void f4(int n) override {
//                     ^^^^^^^^

如果此函数实际上没有重写基函数中的某些内容,则编译器将给出一个错误。

您是想在
cerr行之后再添加一个
}
吗是的,编辑了post您是想在
cerr行之后再添加一个
}
吗是的,编辑了PostC,因为C继承自B,所以它必须使用该形式?C有两个名为f4的方法。一个是从名为
void f4()
的A(通过B)继承的,另一个是从名为
void f4(int)
的B继承的。如果您在没有默认参数值的情况下实现了
void C::f4(int x)
,那么您将覆盖A的实现。但是,正如您所拥有的,您正在重写B对不同方法名称的实现。@selbie
C::f4(int x)
C::f4(int x=1)
是相同的签名,它们都重写
B::f4
A::f4
没有参数。另外,“不同的方法名称”不是最好的描述,因为所有方法都具有相同的名称
f4
。“不同的签名”是官方术语。因为C继承自B,所以它必须使用这种形式?C有两个名为f4的方法。一个是从名为
void f4()
的A(通过B)继承的,另一个是从名为
void f4(int)
的B继承的。如果您在没有默认参数值的情况下实现了
void C::f4(int x)
,那么您将覆盖A的实现。但是,正如您所拥有的,您正在重写B对不同方法名称的实现。@selbie
C::f4(int x)
C::f4(int x=1)
是相同的签名,它们都重写
B::f4
A::f4
没有参数。另外,“不同的方法名称”不是最好的描述,因为所有方法都具有相同的名称
f4
。“不同签名”是官方术语。