Предупреждение: перегруженная виртуальная функция "Base::process" только частично переопределена в классе "производный"
Я получаю предупреждение ниже. часть моего кода:
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"
В любом случае я сделал процесс виртуальной функцией, поэтому я ожидаю, что это предупреждение не должно появиться... В чем причина этого?
5 ответов
Причина предупреждения
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
принести функции для охвата статических вызовов derived::process(int)
даже не скомпилируется. Это потому что Derived не имеет process(int)
в этом случае. Так
Derived *pd = new Derived();
pd->process(0);
а также
Derived d;
d.process(0);
не скомпилируется.
Добавление using
Объявление исправит это, разрешив статический вызов скрытых функций через указатель на Derived* и выберите оператор 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 ";}
};
сейчас:
int main(int argc, char *argv[])
{
derived d;
Base& bref = d;
bref.process(1); // Der::p1
bref.process(1,2); // Der::p2
return 0;
}
Когда вы переопределяете виртуальный метод в классе, любые перегрузки этого метода, которые не переопределяются, скрываются для этого класса и не могут использоваться. Так что в вашем примере, пытаясь позвонить process(int)
на derived
объект потерпит неудачу, потому что переопределено process(int, float)
спрятал это.
Когда вы объявляете метод с тем же именем, что и в Base
эти методы скрыты.
Это тот случай, когда вы переопределяете один метод.
Так
derived d;
d.process(42); // won't compile
Чтобы решить это: добавьте using Base::process
:
class derived: public Base {
public:
using Base::process;
void process(int a, float b);
};
Поскольку предыдущий метод не игнорирует предупреждение lint, другой способ решить это переопределить каждый метод process
:
class derived: public Base {
public:
void process(x) { Base::process(x); }
void process(int a, float b);
};
Вы перекрыли только одну из двух перегрузок process
, Вы пропускаете перегрузку, принимая только 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
перегрузка тоже вderived
; или жесделать
int
перегрузите не виртуальный и позвольте ему вызывать виртуальныйint, float
перегрузки.
Два примечания: (а) Хотя большинство компиляторов принимают это, ;
после того, как тело функции синтаксически неправильно. (б) Защищенные членские переменные обычно не одобряются почти так же, как публичные; Вы должны использовать защищенные методы получения / установки и делать переменные закрытыми.
Короче говоря, частичное переопределение перегруженной функции может быть странным при попытке определить имя.
Кроме того, с точки зрения дизайна. образец вообще странный. У меня есть функция, которая, как я решил, является такой же, чтобы оправдать одно и то же имя: в целом, это молчаливое соглашение о том, что она делает то же самое. Когда вы изменяете поведение функции в дочернем классе, тогда странно, если вы изменяете только ее часть в производном. По сути, его легко читать (используя ~= примерно равный)
// НЕПРАВИЛЬНЫЕ ЗАЯВЛЕНИЯ
1) Base:: process (int) ~= Base:: process (int, float)
2) производная:: процесс (int) ~= производная:: процесс (int, float)
// ЯВНЫЕ ЗАЯВЛЕНИЯ
3) Base::process(int) == производная:: process (int)
4) Base:: process (int, float)! = Производная:: процесс (int, float)
по сути, поскольку 3 и 4 находятся в конфликте, то 2 не может быть правдой.