Ковариация и сокрытие в переполнении стека

Может кто-нибудь объяснить, пожалуйста, причину ввода в каждой строке?

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
}

-4

Решение

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

Образец в Ideone


Примечания:

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

C ++ позволяет ковариант возвращаемые типы (вы можете захотеть иметь virtual A* foo() в A а также virtual B* foo() в B если аргументы совпадают). C ++ не допускает ковариантного или контравариантного аргумент типы, хотя.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]