C++ 虚拟函数和默认参数
假设我有a、B和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;
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对不同方法名称的实现。@selbieC::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对不同方法名称的实现。@selbieC::f4(int x)
和C::f4(int x=1)
是相同的签名,它们都重写B::f4
。A::f4
没有参数。另外,“不同的方法名称”不是最好的描述,因为所有方法都具有相同的名称f4
。“不同签名”是官方术语。