2013-11-11 2 views
12

С помощью следующего кодаКак преобразовать «указатель на тип указателя» на const?

void TestF(const double ** testv){;} 
void callTest(){ 
    double** test; 
    TestF(test); 
} 

я получаю это:

'TestF' : cannot convert parameter 1 from 'double **' to 'const double **' 

Я не могу понять, почему. Почему test не может быть незаполненным к const double**? Почему я должен делать это явно? Я знаю, что

TestF(const_cast<const double**>(test)) 

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

Есть ли какие-то ключевые понятия о const, что мне не хватает?

+4

Вопрос был рассмотрен много раз здесь, но вот запись в FAQ, посвященная этому самому вопросу http://www.parashift.com /c++-faq/constptrptr-conversion.html – AnT

+0

http://stackoverflow.com/questions/1143262/what-is-the-difference-between-const-int-const-int-const-int-const –

+0

Возможный дубликат [константа и указатели на указатели] (http://stackoverflow.com/questions/14441979/constness-and-pointers-to-pointers) – AnT

ответ

8

Язык позволяет неявное преобразование от double ** до const double *const *, но не до const double **. Преобразование, которое вы пытаетесь, неявно нарушает правила корректности const, хотя это не сразу очевидно.

Пример в [де-факто стандартом] C++ FAQ иллюстрирует проблему

http://www.parashift.com/c++-faq/constptrptr-conversion.html

В основном, это правило: когда вы добавляете const на каком-то уровне косвенности, вы должны добавить const к все уровни косвенности все направо. Например, int ***** не может быть неявно преобразован в int **const ***, но он может быть неявно преобразован в int **const *const *const *

+0

«Весь путь вправо», за исключением последнего? – Sam

8

Правильно, что double ** не может быть неявно преобразован в const double **. Однако он может быть преобразован в const double * const *.

Представьте себе такой сценарий:

const double cd = 7.0; 
double d = 4.0; 
double *pd = &d; 
double **ppd = &pd; 
const double **ppCd = ppd; //this is illegal, but if it were possible: 
*ppCd = &cd; //now *ppCd, which is also *ppd, which is pd, points to cd 
*pd = 3.14; // pd now points to cd and thus modifies a const value! 

Так что, если ваша функция не намерена изменять любой из указателей, участвующих, изменить его принять const double * const *. Если он намеревается внести изменения, вы должны решить, являются ли все его модификации безопасными и, следовательно, может использоваться const_cast, или вам действительно нужно передать в const double **.