[С++] вывести Bj из Ak?

Romki

Пусть есть класс А, из которого выводится класс В.
Затем описываются реализации А1, А2 и А3, а также В1 и В2 'абстактных' классов А и В. Есть ли схема, которая позволяла бы использовать класс ВjАk не выводя каждый раз Вj из понадобившегося Аk?

anzakaznov

а теперь по-русски
особенно вот этот кусок:
Затем описываются реализации А1, А2 и А3, а также В1 и В2 'абстактных' классов А и В

Romki

A1, A2, A3 - конкретные реализации, т. е. потомки класса A. То же с B1 и B2.

anzakaznov

едем дальше
использовать класс ВjАk

что значит "использовать"?
не выводя каждый раз Вj из понадобившегося Аk?

что значит "выводя"?
ты что, хочешь объявлять переменные необъявленного класса?

Romki

Ну, допустим понадобился B2, который использует виртуальные методы класса A, описанные в A3.

Dasar

шаблоны?

Gikor

Необязательно

bleyman

Ну, допустим понадобился B2, который использует виртуальные методы класса A, описанные в A3.

Бред какой-то. Объект либо класса B2, либо класса A3. Одновременно этого быть не может (если все дерево наследований выглядит именно так, как описано). Если он класса А3, то его можно приводить только к А. Если он класса В2, то его можно приводить только к А и В.
Видишь ли, объект - он всегда одного конкретного класса, и все виртуальные фенечки происходят для этого объекта только в его цепочке предков (цепочке а не дереве!). А когда ты делаешь тайпкаст, ничего не меняется, потому что рантайм все равно прекрасно знает, какого типа у тебя объект.
Конечно, ты можешь попытаться извратнуться с множественным наследованием. Но я бы тебе не рекомендовал, потому что тогда понять что именно вызывается любой человек сможет только через много минут суровых раздумий, а удержать это знание в голове дольше небольшого количества минут будет невозможно.

Landstreicher

Мне недавно потребовалось точно такое же. Это не изврат, такое бывает нужно в нормальных случаях. Сначала я подумал что так сделать нельзя, но потом понял - можно. Через виртуальное наследование.
А именно:
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

Спасибо. Надо это обдумать.

Romki

Пожалуй, тоже перейду к указателям, хотя у меня скорее все же иная ситуация.
Оставить комментарий
Имя или ник:
Комментарий: