[С++] вывести Bj из Ak?
особенно вот этот кусок:
Затем описываются реализации А1, А2 и А3, а также В1 и В2 'абстактных' классов А и В
A1, A2, A3 - конкретные реализации, т. е. потомки класса A. То же с B1 и B2.
использовать класс ВjАk
что значит "использовать"?
не выводя каждый раз Вj из понадобившегося Аk?
что значит "выводя"?
ты что, хочешь объявлять переменные необъявленного класса?
Ну, допустим понадобился B2, который использует виртуальные методы класса A, описанные в A3.
шаблоны?
Необязательно
Ну, допустим понадобился B2, который использует виртуальные методы класса A, описанные в A3.
Бред какой-то. Объект либо класса B2, либо класса A3. Одновременно этого быть не может (если все дерево наследований выглядит именно так, как описано). Если он класса А3, то его можно приводить только к А. Если он класса В2, то его можно приводить только к А и В.
Видишь ли, объект - он всегда одного конкретного класса, и все виртуальные фенечки происходят для этого объекта только в его цепочке предков (цепочке а не дереве!). А когда ты делаешь тайпкаст, ничего не меняется, потому что рантайм все равно прекрасно знает, какого типа у тебя объект.
Конечно, ты можешь попытаться извратнуться с множественным наследованием. Но я бы тебе не рекомендовал, потому что тогда понять что именно вызывается любой человек сможет только через много минут суровых раздумий, а удержать это знание в голове дольше небольшого количества минут будет невозможно.
А именно:
class A {
// абстрактнй интерфейс A
};
class B {
// абстрактный интерфейс B
};
class C : virtual public A, virtual public B
// интерефейс C есть объединение интерфейсов A и B
}
class A1 : virtual public A
{
// реализация A1 интерфейса A
}
class B1 : virtual public B
{
// реализация B1 интерфейс A
}
void some_function(C *c) // функция хочет на вход объект, поддерживающий интерфейса A и B
class C1 : public A1, public B1, virtual public C
{
// класс C есть объединение реализации A1 и B1
}
C1 *c1 = new C1; // экземпляр C1
some_function(c1); // функция получит на вход экземпляра C1, думая что это C, при этом при вызове
c->method будет вызываться реализациия из A1, B1.
Плюсы: действительно работает (пробовал).
Минусы: трудно понять для неспециалиста по C++, медленно работает. Конвертация C* в A* которая обычно либо ничего не делает, либо отнимает константу теперь требует лазанья по таблицам виртуальных методов. Простой замер показал, что скорость виртуального вызова пустой функции упала где-то на 25% (12 секунд вместо 9 на 500 млн. вызовов).
Почти написав это решения, я понял как сделать проще, понятнее (и быстрее). А именно завел структуру:
struct AandB {
A* a;
B* b;
}
Фактически, тут происходит "ручное" конструирование тех кусков таблицы виртуальных методов, которые используются при реализации виртуальных базовых классов. Здесь в качестве бонуса у стуктур AandB можно перегрузить операции типа +, - (впрочем, это наверное, специфично к моей ситуации).
Спасибо. Надо это обдумать.
Пожалуй, тоже перейду к указателям, хотя у меня скорее все же иная ситуация.
Оставить комментарий
Romki
Пусть есть класс А, из которого выводится класс В.Затем описываются реализации А1, А2 и А3, а также В1 и В2 'абстактных' классов А и В. Есть ли схема, которая позволяла бы использовать класс ВjАk не выводя каждый раз Вj из понадобившегося Аk?