2010-11-09 2 views
30

Согласно this,не имеет информации RTTI, поэтому литье из void* не является законным и имеет смысл.dynamic_cast from "void *"

Если я правильно помню, dynamic_cast от void* работал над gcc.

Не могли бы вы прояснить проблему.

ответ

35

dynamic_cast работает только на полиморфных типов, то есть классы, содержащие виртуальные функции.

В GCC можно dynamic_castкvoid* но не от:

struct S 
{ 
    virtual ~S() {} 
}; 

int main() 
{ 
    S* p = new S(); 
    void* v = dynamic_cast<void*>(p); 
    S* p1 = dynamic_cast<S*>(v); // gives an error 
} 
3

Это правда, что void* не может быть dynamically_cast ed.

Возможно, вы, вероятно, неправильно помните. С г ++ 4.5 и следующий код

struct A { 
    virtual ~A(); 
}; 

int main() { 
    A a; 
    void *p = &a; 
    A* pa = dynamic_cast<A*>(p); 
} 

Я получаю следующее сообщение об ошибке:

cannot dynamic_cast 'p' (of type 'void*') to type 'struct A*' (source is not a pointer to class)

0

Я предполагаю, что вы путаете с dynalic_castкvoid*. Это является законным и получает указатель на наиболее производный объект класса.

dynamic_castотvoid* является незаконным - тип отлиты из должен быть полиморфными - содержать по меньшей мере одну виртуальную функцию (отсчеты виртуальный деструктор тоже).

+0

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

0

Вы можете наложить указатель на полиморфный тип на void *, но не наоборот.

11

В 5.2.7 - Dynamic cast [expr.dynamic.cast] он говорит, что для dynamic_cast<T>(v):

  • Если T тип указателя, v должен быть Rvalue указателя для завершения типа класса
  • Если T является ссылочным типом, v должен быть lvalue полного типа класса (спасибо usta за комментарий к моему отсутствующему этому)

...

  • В противном случае v должен быть указателем или именующим полиморфного типа

Таким образом, нет, (void*)значения а не допускаются.

Давайте подумаем о том, что ваш запрос может означать: скажем, у вас есть указатель, который на самом деле к Derived1*, но код dynamic_cast -ную только знает, что это void*.Предположим, вы пытаетесь применить его к Derived2*, где оба производных класса имеют общую базу. Поверхностно, вы можете подумать, что все указатели указывают на тот же объект Base, который будет содержать указатель на соответствующую таблицу виртуальной диспетчеризации и RTTI, чтобы все могло висеть вместе. Но учтите, что производные классы могут иметь несколько базовых классов, и поэтому необязательный объект-подкласс Base может быть не таким, на который указывает Derived* - доступный только как void*. Это не сработает. Вывод: компилятор должен знать эти типы, чтобы он мог выполнять некоторую настройку указателей на основе соответствующих типов.

 
Derived1* -----> [AnotherBase] 
       [[VDT]Base] <-- but, need a pointer to start of 
       [extra members] this sub-object for dynamic_cast 

(Некоторые ответы говорят о необходимости указателя вы Отливки из быть полиморфного типа, имеющий виртуальные функции. Это все действительно, но немного вводит в заблуждение. Как вы можете видеть выше, даже если void* относится к такому типу, он все равно не будет надежно работать без полной информации о типе, поскольку реальная проблема заключается в том, что void* предположительно указывает на начало производного объекта, тогда как вам нужен указатель на под-объект базового класса из которого извлекается литой тип.)

+0

Если T - тип указателя, v должен быть rзначением указателя на полный тип класса, ... Если T является ссылочным типом, v должно быть lvalue полного типа класса, ... – usta

+1

@usta: fixed , благодаря. –

Смежные вопросы