Я получаю предупреждение ниже.
часть моего кода:
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"
В любом случае, я сделал процесс виртуальной функцией, поэтому я ожидаю, что это предупреждение не должно появиться …
В чем причина этого ??
Причина предупреждения
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)
спрятал это.
Вы перекрыли только одну из двух перегрузок 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 не может быть правдой.
Когда вы объявляете метод с тем же именем, что и в 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);
};
Как и предыдущий метод, не отключайте предупреждение
Другой способ решить это переопределить каждый метод process
:
class derived: public Base {
public:
void process(x) { Base::process(x); }
void process(int a, float b);
};