C ++ приведение программно: это может быть сделано? - PullRequest
5 голосов
/ 28 октября 2008

Допустим, у меня есть базовый класс и несколько производных классов. Есть ли способ привести объект к одному из производных классов без необходимости писать что-то вроде этого:


string typename = typeid(*object).name();
if(typename == "Derived1") {
   Derived1 *d1 = static_cast&lt Derived1*&gt(object);
}
else if(typename == "Derived2") {
   Derived2 *d2 = static_cast &lt Derived2*&gt(object);
}
...
else {
  ...
}

Ответы [ 8 ]

22 голосов
/ 28 октября 2008

Не.

Читайте о полиморфизме. Почти каждая ситуация «динамического приведения» является примером того, как полиморфизм пытается реализовать.

Какое бы решение вы ни приняли в динамическом броске, оно уже было принято. Просто делегируйте реальную работу подклассам.

Вы пропустили самую важную часть вашего примера. Полезная, полиморфная работа.

string typename = typeid(*object).name();
if(typename == "Derived1") {
   Derived1 *d1 = static_cast< Derived1*>(object);
   d1->doSomethingUseful();
}
else if(typename == "Derived2") {
   Derived2 *d2 = static_cast < Derived2*>(object);
   d2->doSomethingUseful();
}
...
else {
  ...
}

Если каждый подкласс реализует doSomethingUseful, все это намного проще. И полиморфный.

object->doSomethingUseful();
9 голосов
/ 28 октября 2008

Вы можете использовать dynamic_cast и проверить на NULL, но я бы настоятельно рассмотрел вопрос о рефакторинге кода.

Если вам нужна специфичная для подкласса обработка, Шаблонный метод может быть полезен, но не зная, чего вы пытаетесь достичь, это только смутное предположение.

5 голосов
/ 28 октября 2008
Derived1* d1 = dynamic_cast< Derived1* >(object);
if (d1 == NULL)
{
    Derived2* d2 = dynamic_cast< Derived2* >(object);
    //etc
}

У меня есть следующие методы для моего типа smartpointer, имитирующие C # 'is' и 'as':

template< class Y > bool is() const throw()
    {return !null() && dynamic_cast< Y* >(ptr) != NULL;}
template< class Y > Y* as() const throw()
    {return null() ? NULL : dynamic_cast< Y* >(ptr);}
4 голосов
/ 28 октября 2008

Вы можете сделать это, используя dynamic_cast, например:

if ( Derived1* d1 = dynamic_cast<Derived1*>(object) ) {
    // object points to a Derived1
    d1->foo();
}
else if ( Derived2* d2 = dynamic_cast<Derived2*>(object) ) {
    // object points to a Derived2
    d2->bar();
}
else {
    // etc.
}

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

3 голосов
/ 28 октября 2008

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

2 голосов
/ 28 октября 2008

Чего именно вы пытаетесь достичь? По моему опыту, такие вещи являются признаком плохого дизайна. Переоцените иерархию классов, потому что цель объектно-ориентированного проектирования - сделать такие вещи ненужными.

1 голос
/ 28 октября 2008

Я думаю, что dynamic_cast - это путь, но я не особенно думаю, что это плохой дизайн для всех возможных условий, потому что объект, который должен быть приведен, может быть предоставлен каким-то сторонним модулем. Допустим, объект был создан плагином, о котором автор приложения не знает. И этот конкретный плагин может создавать объект типа Derived1 (являющийся старой версией) или объект типа Derived2 (являющийся новой версией). Возможно, интерфейс плагина не был предназначен для выполнения конкретных задач, он просто создает объект, поэтому приложение должно выполнять такую ​​проверку, чтобы обеспечить правильное приведение / выполнение. После этого мы можем безопасно вызывать object.doSomethingUsefulThatDoesNotExistInDerived1 ();

1 голос
/ 28 октября 2008

Ваш пример не будет портировать, потому что точный формат имени () не указан. Вы можете попробовать последовательность dynamic_cast с. Dynamic_cast возвращает нулевой указатель, если вы приведете к неверному типу. Однако, если вы делаете такой типизатор, значит что-то не так с вашим дизайном.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...