Incompatible types prevent overriding

Метод производного класса скрывает virtual метод базового класса вместо того, чтобы заменить его

Описание

Этот дефект происходит, когда метод производного класса имеет то же имя и номер параметров как virtual метод базового класса, но:

  • Списки параметров отличаются по крайней мере по одному типу параметра.

  • Списки параметров отличаются по присутствию или отсутствию спецификаторов, таких как const.

Метод производного класса скрывает virtual метод базового класса вместо того, чтобы заменить его.

Риск

  • Вы можете непреднамеренно скрыть метод базового класса вместо того, чтобы заменить его с методом производного класса.

  • Если метод базового класса скрыт, и вы используете объект производного класса вызвать метод параметрами базового класса, метод производного класса называется вместо этого. Для параметров, типы которых не совпадают с аргументами, которые вы передаете, бросок происходит, если это возможно. В противном случае отказ компиляции происходит.

Фиксация

Чтобы заменить базовый класс виртуальный метод с методом производного класса, объявите методы при помощи идентичных списков параметров. Например, измените тип параметра или добавьте const спецификатор при необходимости.

На C++ 11 и позже, можно объявить предназначенные методы переопределения в производном классе при помощи спецификатора override. Когда вы объявляете методы производного класса при помощи спецификатора override, компиляция перестала работать, если списки параметров метода базового класса и метод производного класса отличаются. Методы производного класса не могут скрыть методы базового класса непреднамеренно и переопределение базового класса, который обеспечены виртуальные методы.

В противном случае добавьте линию с помощью Base_class_nameMethodName к объявлению производного класса. Можно затем получить доступ к методу базового класса с помощью объекта производного класса.

Примеры

развернуть все

class Base {
public:
    Base();
    virtual ~Base();
    virtual void func(float i);
    virtual void funcp(float* i);
    virtual void funcr(float& i);
};

typedef double Float;

class Derived: public Base {
public:
    Derived();
    ~Derived();
    void func(Float i);
    void funcp(Float* i);
    void funcr(Float& i);
};

В этом примере, из-за оператора typedef double Float;, Derived методы класса func, funcp, и funcr имейте double аргументы, в то время как Base методы класса с тем же именем имеют float аргументы. Поэтому вы не можете получить доступ к Base методы класса с помощью Derived объект класса.

Дефект появляется на методе, который скрывает метод базового класса. Чтобы найти, какой метод базового класса скрыт:

  1. Перейдите к определению базового класса. На панели Source щелкните правой кнопкой по имени базового класса и выберите Go To Definition.

  2. В определении базового класса идентифицируйте virtual метод, который имеет то же имя как имя метода производного класса.

Коррекция — выводит на экран метод базового класса

Одна возможная коррекция должна использовать тот же тип аргумента для основы и методов производного класса, чтобы позволить заменить. В противном случае, если вы хотите вызвать Base методы класса с float аргументы с помощью Derived объект класса, добавляет линия с помощью Основы:: method_name к Derived объявление класса.

class Base {
public:
    Base();
    virtual ~Base();
    virtual void func(float i);
    virtual void funcp(float* i);
    virtual void funcr(float& i);
};

typedef double Float;

class Derived: public Base {
public:
    Derived();
    ~Derived();
    using Base::func;
    using Base::funcp;
    using Base::funcr;
    void func(Float i);
    void funcp(Float* i);
    void funcr(Float& i);
};
Коррекция — Задает Метод Производного класса при помощи override

Другая коррекция должна явным образом задать методы производного класса как методы переопределения при помощи спецификатора override. Таким образом, ясно, что вы намереваетесь заменить методы базового класса в производном классе. Если методы переопределения имеют различные списки параметров, чем их дубликаты базового класса, код не компилирует. В результате методы производного класса не могут скрыть методы базового класса.

class Base {
public:
    Base();
    virtual ~Base();
    virtual void func(float i);
    virtual void funcp(float* i);
    virtual void funcr(float& i);
};

typedef double Float;

class Derived: public Base {
public:
    Derived();
    ~Derived();
//   Compilation error
//  void func(Float i) override;
//  void funcp(Float* i) override;
//  void funcr(Float& i) override;

    void func(float i) override;
    void funcp(float* i) override;
    void funcr(float& i) override;
};

Закомментированные определения метода имеют различные списки параметров по сравнению со своими дубликатами базового класса. Поскольку методы производного класса объявляются при помощи спецификатора override, отличающиеся списки параметров не скрывают методы базового класса. Вместо этого коду не удается скомпилировать. Используя override спецификатор осуществляет правило, что виртуальные методы в основе и производных классах должны иметь идентичные списки параметров.

namespace Missing_Const {
class Base {
public:
    virtual void func(int) const ;
    virtual ~Base() ;
} ;

class Derived : public Base {
public:
    virtual void func(int) ;

} ;
}

В этом примере, Derived::func не имеет const спецификатор, но Base::func делает. Поэтому Derived::func не заменяет Base::func.

Коррекция — добавляет const Спецификатор к методу производного класса

Чтобы позволить заменить, добавьте const спецификатор к объявлению метода производного класса.

namespace Missing_Const {
class Base {
public:
    virtual void func(int) const ;
    virtual ~Base() ;
} ;

class Derived : public Base {
public:
    virtual void func(int) const;

} ;
}

Постараться не скрывать методы базового класса или превращать виртуальные методы в невиртуальные методы непреднамеренно:

  • Объявите виртуальные методы в базовом классе при помощи спецификатора virtual.

  • Объявите, что виртуальные методы в нефинале вывели базовый класс при помощи спецификатора override.

  • Объявите виртуальные методы в итоговом классе при помощи спецификатора final.

namespace Missing_Ref {

class Obj {
    int data;
};

class Base {
public:
    virtual void func(Obj& o);
    virtual ~Base() ;
} ;

class Derived : public Base {
public:
    virtual void func(Obj o) ;

} ;
}

В этом примере, Derived::func принимает Obj параметр значением, но Base::func принимает Obj параметр ссылкой. Поэтому Derived::func не заменяет Base::func.

Коррекция — ссылка использования для параметра метода производного класса

Чтобы позволить заменить, передайте параметр метода производного класса ссылкой.

namespace Missing_Ref {

class Obj {
    int data;
};

class Base {
public:
    virtual void func(Obj& o);
    virtual ~Base() ;
} ;

class Derived : public Base {
public:
    virtual void func(Obj& o) ;

} ;
}

Постараться не скрывать методы базового класса или превращать виртуальные методы в невиртуальные методы непреднамеренно:

  • Объявите виртуальные методы в базовом классе при помощи спецификатора virtual.

  • Объявите, что виртуальные методы в нефинале вывели базовый класс при помощи спецификатора override.

  • Объявите виртуальные методы в итоговом классе при помощи спецификатора final.

Информация о результате

Группа: Объектно-ориентированный
Язык: C++
Значение по умолчанию: На для рукописного кода, прочь для сгенерированного кода
Синтаксис командной строки: VIRTUAL_FUNC_HIDING
Удар: Средняя
Введенный в R2015b