Предупреждение: перегруженная виртуальная функция "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
// ...
};

В зависимости от того, что вы хотите, вы можете:

  1. Просто переопределить int перегрузка тоже в derived; или же

  2. сделать int перегрузите не виртуальный и позвольте ему вызывать виртуальный int, float перегрузки.

Два примечания: (а) Хотя большинство компиляторов принимают это, ; после того, как тело функции синтаксически неправильно. (б) Защищенные членские переменные обычно не одобряются почти так же, как публичные; Вы должны использовать защищенные методы получения / установки и делать переменные закрытыми.

C++ разрешение перегрузки.

Короче говоря, частичное переопределение перегруженной функции может быть странным при попытке определить имя.

Кроме того, с точки зрения дизайна. образец вообще странный. У меня есть функция, которая, как я решил, является такой же, чтобы оправдать одно и то же имя: в целом, это молчаливое соглашение о том, что она делает то же самое. Когда вы изменяете поведение функции в дочернем классе, тогда странно, если вы изменяете только ее часть в производном. По сути, его легко читать (используя ~= примерно равный)

// НЕПРАВИЛЬНЫЕ ЗАЯВЛЕНИЯ

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 не может быть правдой.

Другие вопросы по тегам