C++ 警告:虚拟函数重载“;基础::过程“;仅在类“中部分重写”;“派生”;
我正处于警告之下。 我的部分代码是:C++ 警告:虚拟函数重载“;基础::过程“;仅在类“中部分重写”;“派生”;,c++,overriding,virtual-functions,name-hiding,C++,Overriding,Virtual Functions,Name Hiding,我正处于警告之下。 我的部分代码是: class Base { public: virtual void process(int x) {;}; virtual void process(int a,float b) {;}; protected: int pd; float pb; }; class derived: public Base{ public: void process(int a,float b); } void derived::p
class Base {
public:
virtual void process(int x) {;};
virtual void process(int a,float b) {;};
protected:
int pd;
float pb;
};
class derived: public Base{
public:
void process(int a,float b);
}
void derived::process(int a,float b){
pd=a;
pb=b;
....
}
我得到以下警告:
Warning: overloaded virtual function "Base::process" is only partially overridden in class "derived"
任何方式,我已经作为虚拟函数的进程,所以我期待这个警告不应该来。。。
这背后的原因是什么???您只重写了
进程的两个重载中的一个。您缺少仅使用int
的重载
class Base {
public:
virtual void process(int x) {;}; // You do *not* override this in derived
virtual void process(int a,float b) {;}; // You do override this
// ...
};
根据您的需要,您可以:
只需在派生的中重写int
重载即可;或
使int
重载非虚拟,并让它调用虚拟int,float
重载
两个旁注:(a)虽然大多数编译器都接受它,但a函数体语法错误后的代码>。(b) 受保护的成员变量通常和公共变量一样不受欢迎;您应该使用受保护的getter/setter并将变量设为私有。当您重写类中的虚拟方法时,未被重写的该方法的任何重载都将隐藏在该类中,并且无法使用。因此,在您的示例中,尝试在派生的对象上调用进程(int)
将失败,因为被重写的进程(int,float)
已将其隐藏。当您声明一个与Base
中的方法同名的方法时,这些方法将被隐藏
当您重写一个方法时就是这种情况
所以
要解决这个问题,请使用Base::process添加:
class derived: public Base {
public:
using Base::process;
void process(int a, float b);
};
class derived: public Base {
public:
void process(x) { Base::process(x); }
void process(int a, float b);
};
与前面的方法一样,不要使lint警告静音,
另一种解决方法是覆盖每个方法过程:
class derived: public Base {
public:
using Base::process;
void process(int a, float b);
};
class derived: public Base {
public:
void process(x) { Base::process(x); }
void process(int a, float b);
};
长话短说,在尝试解析名称时,部分重写重载函数可能会很奇怪
另外,从设计的角度来看。这种模式通常很奇怪。我有一个功能,我已经决定,它是相同的,足以保证相同的名称:一般来说,它是一个默契,它做同样的事情。当您在子类中更改函数的行为时,如果您只在派生类中更改它的一部分,那就很奇怪了。本质上,它很容易阅读(使用~=大约相等)
//隐式语句
1) Base::process(int)~=Base::process(int,float)
2) 派生::进程(int)~=派生::进程(int,float)
//明确陈述
3) 基本::进程(int)=派生::进程(int)
4) 基本::进程(整数,浮点)!=派生::进程(int,float)
本质上,由于3和4是冲突的,那么2不可能是真的。警告的原因是什么
Warning: overloaded virtual function "Base::process" is only partially overridden in class "derived"
你没有覆盖所有的签名,你已经覆盖了
virtual void process(int a,float b) {;}
但不是为了
virtual void process(int x) {;}
此外,当您不重写并且不使用using Base::process
将函数带到作用域时,对派生::process(int)
的静态调用甚至不会编译。这是因为在这种情况下,派生没有进程(int)
。所以
Derived *pd = new Derived();
pd->process(0);
及
不会编译
使用
声明添加,将修复通过指向派生*的指针对隐藏函数进行静态调用并选择运算符d.process(int)进行编译和虚拟分派(通过基指针或引用调用派生函数)进行编译时无警告的问题
class Base {
public:
virtual void process(int x) {qDebug() << "Base::p1 ";};
virtual void process(int a,float b) {qDebug() << "Base::p2 ";}
protected:
int pd;
float pb;
};
class derived: public Base{
public:
using Base::process;
/* now you can override 0 functions, 1 of them, or both
* base version will be called for all process(s)
* you haven't overloaded
*/
void process(int x) {qDebug() << "Der::p1 ";}
void process(int a,float b) {qDebug() << "Der::p2 ";}
};
virtualvoidbase::process(intx)代码>隐藏在导出的中。您可以使用Base::process添加,以解决此问题。只有在静态调用函数时,“…对于该类是隐藏的,不能使用”。您始终可以通过基指针/引用调用它。我发现在静态上下文中调用虚拟函数很奇怪,但有时它是有意义的。所以我觉得只覆盖其中一个重载是完全合理的…@leems只覆盖一个重载当然是合理的,但我无法想象你会想要这种行为。就我个人而言,我认为这是一个设计缺陷,但我可能遗漏了重载解析工作原理或其他方面的细微差别。我所知道的就是在C++中与OOP合作很快就让我向往java。我将避免在虚拟方法中使用默认参数。@ JAROD42:你说得对。既然你这么说了,我甚至还记得Scott Meyers在有效的C++中有一个完整的项目:“永远不要重新定义继承函数的默认参数值”。所以最好使用最后一个选项。@Ashwin:所以我认为这个警告是假阳性。。。顺便说一句,void进程(intx){Base::process(x);}
应该使警告静音…我刚刚在派生类中创建了一个伪进程函数,如下面的void进程(intx){;}。。。。它解决了我的警告…@Ashwin:所以你用与Base
相同的定义覆盖它,我调用Base
以确保它是相同的。我认为这一意图更加明确。我建议添加评论,告诉大家这是无声的皮棉警告。
int main(int argc, char *argv[])
{
derived d;
Base& bref = d;
bref.process(1); // Der::p1
bref.process(1,2); // Der::p2
return 0;
}