Перегрузка виртуальной функции в дочернем классе
Я просто тестирую с помощью концепций виртуального ключевого слова и наследования в С++.
Я написал небольшую программу:
#include<stdio.h>
#include<iostream>
using namespace std;
class cna_MO
{
public:
virtual void print()
{
cout << "cna_MO" << endl;
}
};
class cna_bsc:public cna_MO
{
public:
void print()
{
cna_MO::print();
}
void print(int a)
{
cout << "cna_BSC" << endl;
}
};
class cna_Mo
{
cna_MO *_mo;
public:
cna_Mo()
{
_mo = new cna_bsc;
}
virtual void print(int a)
{
cout << "cna_Mo with arg" << endl;
_mo->print(5);
}
virtual void print()
{
cout << "cna_Mo" << endl;
_mo->print();
}
};
int main()
{
cna_Mo valid_mo;
cout << "old case is started" << endl;
valid_mo.print();
cout << "new case is started" << endl;
valid_mo.print(5);
return 0;
}
Что я здесь сделал, я перегрузил виртуальную функцию в родительском классе в дочернем классе! Это не правильно?
Я получаю ошибки компиляции, как показано ниже:
"temp10.cc", строка 45: Ошибка: слишком много аргументов при вызове на "cna_MO:: print()".
Ответы
Ответ 1
Как только вы перегрузите функцию из базового класса в классе Derived, все функции с тем же именем в базовом классе будут скрыты в классе Derived.
После добавления функции cna_bsc::print(int a)
в производный класс функция cna_MO::::print()
больше не будет видна пользователям класса Derived. Это называется функцией скрытия.
Решение:
Чтобы сделать скрытую функцию видимой в производном классе, вам нужно добавить:
using cna_MO::print;
в разделе public
вашего производного класса cna_bsc
.
Хорошее Чтение:
Что означает, Warning: Derived:: f (char) скрывает Base:: f (double)?
Ответ 2
Это потому, что функция печати в дочернем классе принимает параметр, а оригинал - нет.
в cna_MO (родительский класс):
virtual void print()
в cna_bsc (дочерний класс):
void print(int a)
В основном дочерняя печать не должна принимать аргумент int:
void print()
EDIT:
Может быть, лучше всего было бы сделать передачу int необязательной?
например:
в cna_MO (родительский класс):
virtual void print(int a=-1) {
if (a == -1) {
// Do something for default param
} else {
cout << a;
}
}
в cna_bsc (дочерний класс):
void print(int a=-1)
поэтому, если вы, возможно, предположите, что == -1, они ничего не пропускали.
Фокус в том, что и родительскому, и дочернему нужно один и тот же метод siganture, что означает тот же тип возврата и те же типы аргументов.
Ответ 3
Если у вас есть функция с таким же именем и разными параметрами в производном классе, как у базового класса, то эта функция будет скрыта. Вы можете найти более подробную информацию здесь..
Вы можете вызвать конкретную скрытую функцию, вызвав как Base::hiddenFun();
Ответ 4
Это не сработает, поскольку с учетом cna_MO *
вы можете видеть во время компиляции, что заостренный объект не обязательно (обязательно) имеет перегрузку int. Если он фактически указал на объект базового класса, _mo->print(5);
действительно нечего было бы вызывать. Также может быть бесконечное число (еще не реализовано) производных классов, которым не нужно поддерживать этот вызов.
-
Каждый производный класс должен иметь print(int)
- объявить его в базовом классе.
-
Каждый производный класс не должен иметь print(int)
- cna_Mo
работает только с cna_bsc
, поэтому член должен быть cna_bsc* _mo
.
Ответ 5
В идеале ваша печать, которая принимает int, должна иметь другое имя, но если вы хотите, чтобы обе функции назывались печатью, вы должны сделать их не виртуальными и заставить их вызывать защищенные виртуальные функции.
class cna_MO
{
public:
void print() { doPrint(); }
protected:
virtual void doPrint()
{ cout << "cna_MO" << endl;
}
};
class cna_bsc:public cna_MO
{
protected:
virtual void doPrint()
// although with implementation no need to override it
{
cna_MO::print();
}
public:
void print(int a)
{
doPrintInt( a );
}
protected:
virtual void doPrintInt( int )
{
cout << "cna_BSC" << endl;
}
};
Ответ 6
Если вы ДЕЙСТВИТЕЛЬНО ДОЛЖНЫ делать это так, то есть иметь указатель на один класс и инициализировать как производный класс, нет выбора, кроме как всегда указывать указатель на правильный тип при его использовании. В этом случае ((cna_bsc*)_mo)->print(5);