У меня есть ситуация, подобная следующей:
class Getter
{public: virtual void doSomething {std::cout<<"Nothing";};
};
class Getter_A: public Getter
{public: void doSomething {std::cout<<"A";};
};
class Getter_B: public Getter
{public: void doSomething {std::cout<<"B";};
};
Затем у меня есть блок кода, в котором я хочу использовать одну из этих вещей Getter.Таким образом, на английском у меня было бы следующее:
{Getter & getter=wantA?Getter_A():Getter_B;
getter.doSomething();
};
Конечно, в C ++ это не совсем работает, потому что троичный оператор не достаточно умен, чтобы искать общий базовый класс, поэтому я делаюэто:
{Getter & getter=wantA?(Getter &)Getter_A():(Getter &)Getter_B;
getter.doSomething();
};
Это элегантно и читабельно.Вопрос в том, работает ли он в C ++.Поскольку компиляторов C ++ нет, и поскольку я не могу найти однозначного ответа в справочнике, я спрашиваю здесь.
Общее основание: «Компиляторы языка, похожего на C ++» Iпопытался сделать следующее:
- Создать объект
Getter_A
или Getter_B
. - Позвоните
doSomething
. - Удалите созданный объект.
Открытый вопрос: что делать для вызова?
Clang на Mac вызывает Getter_A::doSomething()
или Getter_B::doSomething()
.Таким образом, за кадром эта ссылка Getter&
является ссылкой либо на объект Getter_A
, либо на объект Getter_B
.
Visual C ++ 6.0 вызывает Getter::doSomething()
.Таким образом, за кадром он удаляет Getter_A
сущность из созданного объекта и вместо этого делает ссылку на голый объект Getter
.Это становится более впечатляющим, если Getter::doSomething
сделано чистым, а не иметь тело.
Теперь Visual C ++ 6.0 славится не компиляцией C ++, а совершенно другим языком с тем же именем.Тем не менее, было бы хорошо узнать, ожидает ли C ++ (в отличие от идеи того или иного автора о том, что такое C ++ автор) компилятора, что ссылка на базовый класс по-прежнему будет ссылкой на исходный объект во всехего великолепная виртуальность, или то, правильно ли Microsoft в этом случае раздеть объект обнаженным при приведении ссылки.
Обход, который я придумал и протестировал, это:
{Getter_A a; Getter_B b;
Getter &getter=*(wantA?(Getter *)&a:&b);
getter.doSomething();
}
, который, поскольку компиляторы уважают конфиденциальность указателей, кажется безопасным везде.Но это немного грязный язык, и было бы неплохо узнать, что реальный, соответствующий стандартам компилятор C ++ будет делать с приведением ссылок на базовый класс.