Проблемы с частичными переопределениями функции класса в C++

Есть ли какая-либо проблема с частично переопределяющим рядом виртуальных функций, определенных базовым классом?

Мой компилятор обеспечивает соблюдающее предупреждение:

overloaded virtual function "MyBaseClass::setValue" is only partially overridden in class "MyDerivedClass".

Классы похожи на это:

class MyBaseClass
{
public:
    virtual void setValue(int);
    virtual void setValue(SpecialType*);
}

class MyDerivedClass : public MyBaseClass
{
public:
    virtual void setValue(int);
}

Простой способ избавиться от этого предупреждения состоит в том, чтобы использовать различные названия основных функций, но я хотел знать, был ли какой-либо неопровержимый довод для фиксации этого определенного предупреждения. Я не полагаю, что это нарушает стандарт C++. Мое предположение - то, что это должно предупредить программиста, что они, возможно, забыли реализовывать поведение для всех возможных входных типов. В нашем случае это является намеренным для исключения некоторых определенных типов.

Вы препятствовали бы подавлению этого предупреждения в целом?

6
задан FP. 13 January 2010 в 15:29
поделиться

3 ответа

Переопределение для setValue(int) скрывает setValue(SpecialType*) базового класса (см. C++ FAQ Lite), так что при попытке вызова setValue(new SpecialType()) вы получите ошибку.

Вы можете избежать этого, добавив директиву using к производному классу, который "импортирует" перегрузки из базового класса:

class MyDerivedClass : public MyBaseClass
{
public:
    using MyBaseClass::setValue;
    virtual void setValue(int);
};
13
ответ дан 8 December 2019 в 12:20
поделиться

Предупреждение правильное, он называется «скрытие имени». Переменная типа MyderedClass не может вызвать setValue (SpecialType *) .


Теперь я собираюсь взрывно отрываться чужой блог :

Перегрузка и имя, скрывающиеся в C ++

в телефонном разговоре с Брэдом прошлой ночью, он рассказал мне о странной проблеме, которую он встречался в своей новой работе C ++. Конечно, это, вероятно, не имеет большого значения для людей с обширным опытом C ++, но для тех из нас, которые живут в управляемых кодевых мирах, это казалось странным.

В C ++, когда у вас есть класс с перегруженным методом (функция элементов, что, как вы хотите вызвать его), и вы затем расширяете и переопределите этот метод, вы должны переопределить все перегруженные методы.

Я понимаю тот случай, когда вы изменили метод подписи в дочернем классе, тем самым недействуя установленный интерфейс. В этом случае, хотя, кажется, контрактю, так как вы не меняете интерфейс, но выборочно переоценивают. Который отличается.

Например:

class FirstClass
{
public:
        virtual void MethodA (int);
        virtual void MethodA (int, int);
};

void FirstClass::MethodA (int i)
{
    std::cout << "ONE!!\n";
}

void FirstClass::MethodA (int i, int j)
{
     std::cout << "TWO!!\n";
}

простой класс здесь с двумя методами (или одним перегруженным методом). Вы хотите переопределить двухпараметрическую версию, поэтому вы продолжаете следующую:

class SecondClass : public FirstClass
{
public:
    void MethodA (int);
};

void SecondClass::MethodA (int i)
{
    std::cout << "THREE!!\n";
}

Теперь, когда вы используете экземпляр SecondClass, большинство программистов Java или C # могут предположить, что вы можете позвонить:

int main ()
{
    SecondClass a;
    a.MethodA (1);
    a.MethodA (1, 1);
}

Однако второй звонок выиграл Работа, поскольку двухпараметрический метод не виден. Вы можете получить указатель и добраться до FirstClass, но экземпляр второгокласса не наследует непосредственным методам непосредственно.

6
ответ дан 8 December 2019 в 12:20
поделиться

Понятно, что компилятор хочет предупредить вас: вы создали подкласс, который ведет себя по-разному, когда дает ему INT , но вы не изменили его поведение при предоставлении его Specialtype * .

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

Я хотел бы, чтобы компилятор предупредил меня сложнее, время я проигнорировал! Мой переопределенный метод оказался компиляцией и хорошо работать в моем сценарии, но какой-то другой сценарий пошел действительно не так из-за перегрузки, не переоцененной.

Подумайте дважды, прежде чем отключить это предупреждение!

Если вы хотите, чтобы исходное поведение сохранилось, легко просто позвонить родительскую функцию:

class MyDerivedClass : public MyBaseClass {
   virtual void setValue(int);
   // explicit: keep original behavior for SpecialType
   virtual void setValue( SpecialType* p ) { MyBaseClass::setValue(p); } 
};
0
ответ дан 8 December 2019 в 12:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: