Несовместимые типы предотвращают переопределение

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

Описание

Несовместимые типы предотвращают переопределение, происходит, когда метод производного класса имеет то же имя и номер параметров как метод базового класса virtual, но:

  • Отличайтесь по крайней мере по одному типу параметра.

  • Отличайтесь по присутствию или отсутствию спецификаторов, таких как const.

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

Риск

Риски включают следующее:

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

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

Фиксация

Возможные решения включают следующее:

  • Если вы хотите, чтобы метод производного класса заменил метод базового класса, изменил интерфейс метода производного класса.

    Например, измените тип параметра или добавьте спецификатор const при необходимости.

  • В противном случае добавьте строку using Base_class_name::method_name в объявление производного класса. Таким образом можно получить доступ к методу базового класса с помощью объекта производного класса.

Примеры

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

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, добавьте строку using Base::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);
};
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;

} ;
}
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) ;

} ;
}

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

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

Введенный в R2015b