У меня вопрос, как использовать один указатель на разные объекты A или B.
Вы можете сделать это без виртуальных функций как таковых. Но все, что вы действительно будете делать, это написать реализацию V-таблицы и виртуальных функций.
Если бы я собирался вручную реализовать виртуальные функции, я бы основывал все это на объекте Boost.Variant. Вариант будет эффективно хранить данные члена для каждого класса. Чтобы вызвать функцию, вы используете вариант функтора посетителя. Каждая «виртуальная функция» будет иметь свой собственный функтор посетителей, который будет иметь разные перегрузки оператора () для каждого из возможных типов в варианте.
Так что вы можете иметь это:
typedef boost::variant<StructA, StructB, StructC> VirtualClass;
Вы можете сохранить любой из этих объектов в варианте. Вы бы вызвали «виртуальную функцию» на объекте так:
VirtualClass someObject(StructA());
boost::apply_visitor(FunctorA(), someObject);
Класс FunctorA - это ваша виртуальная реализация функции. Это посетитель, определяемый так:
class FunctorA : public boost::static_visitor<>
{
void operator()(StructA &arg){
//Do something for StructA
}
void operator()(StructB &arg){
//Do something for StructB
}
void operator()(StructC &arg){
//Do something for StructC
}
}
Посетители могут иметь возвращаемые значения, которые возвращаются apply_visitor
. Они могут принимать аргументы, сохраняя аргументы как члены класса посетителя. И так далее.
Лучше всего, если вы когда-нибудь измените свой тип варианта, добавив новые «производные классы», вы получите ошибки компилятора для любых функторов, у которых нет перегрузок для новых типов.
Но, честно говоря, вы должны просто использовать виртуальные функции.