Приведение C++ программно:можно ли это сделать?

StackOverflow https://stackoverflow.com/questions/243082

  •  04-07-2019
  •  | 
  •  

Вопрос

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


string typename = typeid(*object).name();
if(typename == "Derived1") {
   Derived1 *d1 = static_cast< Derived1*>(object);
}
else if(typename == "Derived2") {
   Derived2 *d2 = static_cast < Derived2*>(object);
}
...
else {
  ...
}
Это было полезно?

Решение

Не.

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

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

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

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();

Другие советы

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

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

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);}

Вы можете сделать это, используя 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.
}

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top