Может кто-нибудь объяснить, пожалуйста, причину ввода в каждой строке?
Class A {
bool f(A* a) { return true; }
}
class B : public A {
bool f(B* b) { return false; }
}
void f() {
A* a = new A();
A* ab = new B();
B* b = new B();
a->f(a); a->f(ab); a->f(b); // true, true, true
ab->f(a); ab->f(ab); ab->f(b); // true, true, true
b->f(a); b->f(ab); b->f(b); // error, error, false
}
B
имеет два не виртуальных метода с одинаковым именем: bool f(A*)
а также bool f(B*)
,
Обычно это были бы перегрузки; но так как один был унаследован от базового класса, он скрыт последним. Он по-прежнему доступен, ему просто нужен специальный синтаксис для вызова, например:
B b;
B* param;
b.f(param); // calls B::f(B*)
b.B::f(param); // same
b.A::f(param); // calls the hidden A::f(A*)
Так:
a->f(a); a->f(ab); a->f(b);
Это легко: a
имеет тип A*
, так A::f(A*)
будет вызван и аргумент типа B*
будет преобразован в A*
,
ab->f(a); ab->f(ab); ab->f(b);
То же самое происходит, так как ab
также имеет тип A*
,
b->f(a); b->f(ab);
Это не может работать с b
имеет тип B*
а также b->f
может относиться только к B::f(B*)
(A::f
скрыт). Вы не можете неявно конвертировать из A*
в B*
,
Вы можете явно упомянуть скрытый метод:
b-> A :: F (а); b-> A :: F (аb);
И последнее работает, просто звонки B::f(B*)
:
b->f(b);
Примечания:
Здесь не имеет значения, являются ли функции виртуальными или нет. У них разные типы аргументов, поэтому один не может переопределить другой. Один может только скрыть другого.
C ++ позволяет ковариант возвращаемые типы (вы можете захотеть иметь virtual A* foo()
в A
а также virtual B* foo()
в B
если аргументы совпадают). C ++ не допускает ковариантного или контравариантного аргумент типы, хотя.
Других решений пока нет …