Почему приведение типов const void * допустимо в C, а не в C ++ без использования static_cast - PullRequest
3 голосов
/ 26 февраля 2020

Есть несколько вопросов с похожими именами в StackOverflow, таких как этот и этот .et c

Однако ни один из них ответил на вопросы в моей голове ...

Справочная информация о проблеме:

Я включаю заголовочный файл C в код C ++. Код проблемного c C показан ниже:

// C header file
static inline bool post_request(const customer_t *requester, const void *packagevoid)
{
    const pkg_req_t *pkg = packagevoid;
    ...
    ... // some other code
}

Компилятор пожаловался, что:

/<project_path>/handler_util.h:250:26: error: invalid conversion from 'const void*' to 'const const pkg_req_t*' {aka 'const pkg_req_s*'} [-fpermissive]
const pkg_req_t *pkg = packagevoid;
                       ^~~~~~~

Я изменил преобразование, чтобы явно использовать static_cast:

// C header file: fixed
static inline bool post_request(const customer_t *requester, const void *packagevoid)
{
#ifdef __cplusplus
  const pkg_req_t *pkg = static_cast<const pkg_req_t*>(packagevoid);
#else
   const pkg_req_t *pkg = packagevoid;
#endif
    ...
    ... // some other code
}

Вопросы:

  1. const pkg_req_t *pkg = packagevoid; --- почему это допустимо в C, но выдает ошибку в C ++?
  2. Является ли static_cast элегантным решением в этом случае? --- Я задаю этот вопрос, потому что кажется, что const_cast<pkg_req_t*>reinterpret_cast<const pkg_req_t*> также работает. Какой лучше?
  3. Почему в сообщении об ошибке компиляции компилятор сообщает "[-fpermissive]" в конце сообщения об ошибке?

1 Ответ

4 голосов
/ 26 февраля 2020

почему это допустимо в C, но выдает ошибку в C ++?

В C ++ неявное преобразование из void* в T* недопустимо, потому что это не «безопасное» преобразование. Разыменование T* приведет к неопределенному поведению, если только void* на самом деле не указывает на объект T.

К моменту создания C ++ было слишком поздно, чтобы запретить этот тип неявного преобразования в C, потому что это нарушит весь код, который делает это:

T* p = malloc(sizeof(T));  // malloc returns void*

Следовательно, он по-прежнему разрешен в C.

Является ли static_cast элегантным решением в этом case?

Да, это «лучший метод» для преобразования из const void* в const T*.

static_cast менее опасен, чем const_cast и reinterpret_cast, поэтому следует отдавать им предпочтение. dynamic_cast менее опасен, чем static_cast, но его нельзя использовать в этой ситуации.

В сообщении об ошибке компиляции почему компилятор сообщает «[-fpermissive]» в конце сообщение об ошибке?

Компилятор сообщает, что если вы скомпилируете свой код с флагом -fpermissive, он примет неявное преобразование из const void* в const T*, даже если стандарт не допустить этого.

...