elgaabeb Ответов: 3

C++ cross-casting практический пример использования


Привет,

Просто чтобы понять использование перекрестного литья на практике,
Может ли кто-нибудь привести мне практический пример использования перекрестного литья ?


Тнх.

Richard MacCutchan

Я знаю, что такое кастинг, но что вы подразумеваете под перекрестным кастингом?

elgaabeb

Определение Дэнни Калева: перекрестное приведение преобразует многократно унаследованный объект в один из его вторичных базовых классов.

Maximilien

это : http://www.objectmentor.com/resources/articles/crosscst.pdf (PDF-файл)?

Sergey Alexandrovich Kryukov

Может быть, полный ответ будет опубликован как таковой.
Что касается практического применения... не уверен, для меня это сомнительно...
--СА

elgaabeb

Я видел эту статью, она, кажется, находится в контексте исследования, и это не так ясно.
Спасибо за ваш комментарий :)

Maximilien

Я не хотел публиковать его в качестве ответа, потому что еще не полностью прочитал его и нашел в гугле; черт возьми, я даже не уверен, действительно ли он относится к первоначальному вопросу.

Philippe Mori

Множественное наследование и, в частности, виртуальное происхождение, как правило, не рекомендуются... поэтому перекрестное литье редко полезно в реальной жизни. Это, главным образом, академический.

В большинстве случаев, когда множественное наследование кажется решением, реализация множественного интерфейса, вероятно, является адекватной.

elgaabeb

Я на 100% согласен с тобой. После нескольких часов поисков я ничего не нашел о практическом использовании перекрестного литья.
Я разместил здесь вопрос, чтобы подстрекнуть разработчиков expierience в надежде найти ответ :).

3 Ответов

Рейтинг:
4

elgaabeb

Привет,

Спасибо вам всем за ваши наряды.
Извините за поздний отзовешься :)
Я искал практический пример, но это будет зависеть от дизайна проекта, поэтому я приведу общий пример.
Представьте себе, что у нас есть четыре класса : животное, летун, собака, корона.

class Animal {
public:
	virtual ~Animal() {};
	void talk (string sound) {
	cout << " Grrrr " << (char *)&sound <<  endl;
}
};


class Flyer {
public:
	void fly (string destination) {
	cout << " Flying to " << (char *)&destination <<  endl;
}
}; 

class Dog:public Animal{
};


class Crow:public Animal, public Flyer{
};


Для сохранения объекта тип собаки и ворона нам нужно сделать восходящее преобразование к базовому классу животных.
когда нам нужно вызвать метод fly() каждой вороны, нам нужно знать, наследуется ли животное от класса Flyer или нет, это делается с помощью перекрестного приведения :

Flyer* myAnimal = dynamic_cast<Flyer*>(pAnimal);

 if(!myAnimal)
       cout<<" my animal can't fly :( ..."<<endl;

else

       cout<<" my animal can flye :) ..."<<endl;




Я надеюсь, что это будет полезно :).


Рейтинг:
21

Paulo Zemek

Я думаю, что могу привести пример перекрестного литья.
Я буду использовать интерфейсы, чтобы привести пример, но в C++ это будет другой класс...

В .И это является очень распространенным явлением, что многие классы реализуют интерфейс IDisposable.
Теперь у вас есть список общего типа (скажем, Control), но этот общий тип не является одноразовым типом.

Использование обычного приведения к IDisposable приведет только к сбою программы при вызове Dispose.
Но тогда, очищая список, вы также Хотите избавиться от всех тех объектов,которые могут быть IDisposable.

В .Net мы будем использовать оператор "as". Если результат отличается от null тогда мы сможем избавиться от него. То же самое будет и с использованием C++.


Хотите другие образцы?
Хорошо ... представьте, что у вас есть базовый класс для Сериализуемых объектов (объектов, которые могут сохранять себя в файл).
Serialize получает только тот файл (поток), в который он будет сохранен.
Но для некоторых объектов вы можете вызвать специальный вид сохранения. Таким образом, вы проверяете, поддерживает ли объект это специальное сохранение (то есть он наследуется от другого, не связанного с базовым классом). Если он поддерживает, то вы его используете.


elgaabeb

С тобой все в порядке.

Рейтинг:
2

Emilio Garavaglia

Это типично, когда вы знаете объект через интерфейс и хотите получить доступ к другому интерфейсу того же самого объекта:

class ia
{
public:
    virtual void a1() =0;
    virtual void a2() =0;
    virtual ~ia() {}
};

class ib
{
public:
    virtual void b1() =0;
    virtual void b2() =0;
    virtual ~ib() {}
};

class agg1:
    public ia,
    public ib
{
public:
    virtual void a1() { std::cout << "a1 in agg1" << std::endl; }
    virtual void a2() { std::cout << "a2 in agg1" << std::endl; }
    virtual void b1() { std::cout << "b1 in agg1" << std::endl; }
    virtual void b2() { std::cout << "b2 in agg1" << std::endl; }
};

class agg2:
    public ia,
    public ib
{
public:
    virtual void a1() { std::cout << "a1 in agg2" << std::endl; }
    virtual void a2() { std::cout << "a2 in agg2" << std::endl; }
    virtual void b1() { std::cout << "b1 in agg2" << std::endl; }
    virtual void b2() { std::cout << "b2 in agg2" << std::endl; }
};

int main()
{
    ia* pa1(new agg1);
    ia* pa2(new agg2);

    pa1->a1();
    pa1->a2();
    pa2->a1();
    pa2->a2();

    ib* pb1(dynamic_cast<ib*>(pa1)); // CROSS CAST from ia to ib thanks to agg1
    ib* pb2(dynamic_cast<ib*>(pa2)); // CROSS CAST from ia to ib thanks to agg2

    if(pb1)
    {
        pb1->b1();
        pb1->b2();
    }
    if(pb2)
    {
        pb2->b1();
        pb2->b2();
    }

    delete pa1;
    delete pa2;
}


Dalek Dave

хороший ответ.