непонятки с множественным наследованием
От: sadomovalex Россия http://sadomovalex.blogspot.com
Дата: 25.03.05 14:56
Оценка:
Всем добрый день

Есть два базовых класса:

#include <iostream>
#include <list>

using namespace std;

//первый базовый класс
class A
{
public:
    void foo1() { cout << "A::foo1" << endl; }
};

//второй абстрактный базовый класс
class B
{
public:
    virtual void foo2() = 0;
};

//два производных класса
class C1: public A, public B
{
public:
    void foo2() { cout << "C1::foo2" << endl; }
};

class C2: public A, public B
{
public:
    void foo2() { cout << "C2::foo2" << endl; }
};

//используем следующим образом
int main()
{
    list<A*> lst;
    lst.push_back(new C1());
    lst.push_back(new C2());

    for(list<A*>::iterator it = lst.begin(); it != lst.end(); ++it)
    {
        B* b = (B*)(*it);
        b->foo2(); // здесь падает
    }
    //...

    return 0;
}


На выделенном фрагменте программа падает. Если же делать так:
class C1: public A, virtual public B
{
public:
    void foo2() { cout << "C1::foo2" << endl; }
};

class C2: public A, virtual public B
{
public:
    void foo2() { cout << "C2::foo2" << endl; }
};

то все нормально отрабатывает. Что за поведение такое и правомерно ли указанное решение проблемы ? Может кто-нибудь прокомментировать
"Что не завершено, не сделано вовсе" Гаусс
Re: непонятки с множественным наследованием
От: _DAle_ Беларусь  
Дата: 25.03.05 15:17
Оценка: 6 (1) +1
Здравствуйте, sadomovalex, Вы писали:

S>Всем добрый день


S>Есть два базовых класса:


S>
S>        B* b = (B*)(*it);
S>

Используй dynamic_cast вместо этого преобразования.
Re: непонятки с множественным наследованием
От: avitya  
Дата: 25.03.05 15:19
Оценка: 2 (1) -1
Здравствуйте, sadomovalex, Вы писали:

Проблема в том, что простой каст на B* не работает из-за расположения объектов в памяти. С-cast об этом ничего не знает. Надо делать static_ или dynamic_cast. Можно обойтись cast-om на B*... однако не работает ибо A* к B* не приводится. Поэтому надо сделать следующее:
B* b = static_cast<C1*>(*it);
Хотя тоже не элегантно, но работать уже будет.
И вот вы видите — все недостатки множественного наследования.
Re[2]: непонятки с множественным наследованием
От: Leshi Россия  
Дата: 25.03.05 15:27
Оценка:
Здравствуйте, _DAle_, Вы писали:

S>>
S>>        B* b = (B*)(*it);
S>>

_DA>Используй dynamic_cast вместо этого преобразования.
Не пойдет. Преобразовать из A* в B* неизвестно как. Я думаю, что правильнее всего будет завести промежуточный тип:

class A
{
public:
    void foo1() { cout << "A::foo1" << endl; }
};

//второй абстрактный базовый класс
class B
{
public:
    virtual void foo2() = 0;
};
class C: public A, public B
{
};
//два производных класса
class C1: public C
{
public:
    void foo2() { cout << "C1::foo2" << endl; }
};

class C2: public C
{
public:
    void foo2() { cout << "C2::foo2" << endl; }
};

Вот тогда можно будет dynamic_cast использовать.
... << RSDN@Home 1.1.3 stable >>
Re[2]: непонятки с множественным наследованием
От: Leshi Россия  
Дата: 25.03.05 15:42
Оценка: +1
Здравствуйте, avitya, Вы писали:

A>И вот вы видите — все недостатки множественного наследования.

Не, бери глюбже! И вот мы все лицезреем недостатки НТП. Ведь когда главным и единственным орудием труда были лапы и хвост такой проблемы возникнуть просто не могло бы!
... << RSDN@Home 1.1.3 stable >>
Re[3]: непонятки с множественным наследованием
От: sadomovalex Россия http://sadomovalex.blogspot.com
Дата: 25.03.05 15:46
Оценка:
Здравствуйте, Leshi, Вы писали:

L>Не пойдет. Преобразовать из A* в B* неизвестно как. Я думаю, что правильнее всего будет завести промежуточный тип:


L>Вот тогда можно будет dynamic_cast использовать.


Почему не пойдет — у меня в контейнере гарантировано будут храниться C1 или C2. А dynamic_cast может использоваться для cross cast-инга. В MSDN-е:

A   A
|   |
B   C   D
| _ | _ |
    |
    E


The dynamic_cast operator can also be used to perform a “cross cast.” Using the same class hierarchy, it is possible to cast a pointer, for example, from the B subobject to the D subobject, as long as the complete object is of type E.


Я сам до этого старался обходить множественное наследование — а здесь не получилось, вот и напоролся
"Что не завершено, не сделано вовсе" Гаусс
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.