Я не мог найти однозначного ответа на этот простой, но важный случай. (Буду признателен, если кто-нибудь направит меня к ответу).
Допустим, у меня есть два вида наследования: класс A, который является базовым классом класса B, и класс C, который является базовым классом класса D, и выполняю дополнительную работу (зная, что на самом деле это указатель на D).
Теперь предположим, что у класса A есть виртуальная функция foo, которая принимает в качестве параметра указатель на C. Чего я хотел бы добиться, так это того, что всякий раз, когда A вызывает «foo», он будет действовать так, как если бы он получил указатель на C, и всякий раз, когда B вызывает foo, он будет действовать так, как если бы получил указатель на D.
Компилятор позволил бы мне передать объект, который был инициализирован как: C* c = new D();, но внутри 'foo', насколько я могу судить, нет никакого способа сказать, что на самом деле мы получили указатель на D без использования dynamic_cast.
Вот набросок того, о чем я думаю:
class C {};
class D : C {// has more functions };
class A {
public:
virtual void foo (C* c) { //do something with c* };
};
class B : A {
public
virtual void foo (C* c) { // call A::foo()
//do something with c knowing that c* as actually a D*
}
};
Использование dynamic_cast внутри B::foo кажется неизбежным для достижения того, чего я хочу. Я знаю, что вообще говоря, использование dynamic_cast предполагает плохой дизайн ООП, поскольку он может нарушить LSP, но я не могу придумать других способов добиться того, чего я хочу.
Я хотел бы услышать некоторые предложения - может быть, как бы изменить дизайн, или даже "динамический_каст необходим" будет в порядке.
Надеюсь я понятно изложил свою мысль, если нет - уточню свой вопрос.
Обновление: возможно, я должен был упомянуть об этом раньше (и, кстати, я не просто придумываю это, мне действительно приходилось программировать что-то подобное в университете), но идея о том, что пятый класс, скажем, E будет содержать массив ( или список или что-то еще) типа A, и у меня есть алгоритм, который выполняет итерацию по этому массиву, и для каждого элемента он должен вызывать этот метод «foo» - где, если класс на самом деле был A *, он должен работать как раньше, и если это B *, он должен выполнить «foo» класса B.
Что-то вроде этого:
//within class E
A** arrayOfAs; //(and B's)
for (int i = 0 ; i < lengthOfArray ; ++i )
{
arrayOfAs[i]->foo(/*someObject*/);
}
Спасибо!