2009-04-01 2 views
5

У меня был следующий код на C++, где аргумент моего конструктора в объявлении имел разную константу, чем определение конструктора.Несоответствие между определением конструктора и объявлением

//testClass.hpp 
class testClass { 
    public: 
    testClass(const int *x); 
}; 

//testClass.cpp 
testClass::testClass(const int * const x) {} 

Я был в состоянии собрать это без каких-либо предупреждений с помощью G ++, следует этот код компиляции или, по крайней мере, дать некоторые предупреждения? Оказывается, встроенный компилятор C++ на 64 бит Solaris дал мне ошибку компоновщика, вот как я заметил, что проблема была.

Каково правило для сопоставления аргументов в этом случае? Это для компиляторов?

ответ

7

В подобных случаях спецификатору const разрешается использовать ommitt ed из объявления , поскольку он ничего не изменяет для вызывающего.

Это имеет значение только для контекста деталей реализации. Поэтому именно по определению , но не .

Пример:

//Both f and g have the same signature 
void f(int x); 
void g(const int x); 

void f(const int x)//this is allowed 
{ 
} 

void g(const int x) 
{ 
} 

Любой вызова п не будет все равно, что вы собираетесь рассматривать его как константы, потому что это ваша собственная копия переменной.

С int * const x, это то же самое, это ваша копия указателя. Можете ли вы указать на что-то другое, не имеет значения для вызывающего.

Если вы опустили первый const, хотя в const int * const, то это изменит ситуацию, поскольку это имеет значение для вызывающего, если вы измените данные, на которые указывает.

Ссылка: Стандарт C++, 8.3.5 пункт 3:

«Любой CV-классификатор изменение типа параметра удаляется ... Такие CV-классификаторы влияют только на определение параметра с тела функции, они не влияют на тип функции»

+0

Просьба указать ссылку на стандарт. –

+0

Я написал об этом здесь, если вам нужно больше примеров: http://stackoverflow.com/questions/269882/c-const-question/274888#274888 –

+0

@ onebyone.livejournal.com: Спасибо. –

4

Думай об этом как же разница между

//testClass.hpp 
class testClass { 
    public: 
    testClass(const int x); 
}; 

//testClass.cpp 
testClass::testClass(int x) {} 

Который также компилирует. Вы не можете перегружать на основе константы параметра pass-by-value. Представьте себе такой случай:

void f(int x) { } 
void f(const int x) { } // Can't compile both of these. 

int main() 
{ 
    f(7); // Which gets called? 
} 

От стандарта:

декларации параметров, которые отличаются только в присутствии или в отсутствии сопзЬ и/или летучих эквивалентны. То есть константы const и volatile для каждого параметра игнорируются при определении , какая функция объявляется, определяется или вызывается. [Пример:

typedef const int cInt; 
int f (int); 
int f (const int); // redeclaration of f(int) 
int f (int) { ... } // definition of f(int) 
int f (cInt) { ... } // error: redefinition of f(int) 

-end пример] Только Const и летучие типа спецификаторы на внешнем уровне типа параметра спецификации игнорируются в этом моды; Const и летучие типа спецификаторы похоронен в пределах спецификации типа с параметра являются значительными и может быть использован для различает перегруженную функцию declarations.112) В частности, для любого типа Т, «указатель на T» «указатель Const Т»и„указатель на летучего Т“рассматривается различные типов параметров, так же как„ссылка на Т“,„ссылку на константную Т“и „ссылка на“летучий Т.

0

ли const int * const x не то же самое, как const int * x becus u уже сделал сост?

+0

Нет. В первом случае x является константным указателем на константное целое число. Во втором случае x является указателем * не const const для целочисленного числа const. –

+0

В частности, в первую очередь вы не можете изменять ни x, ни * x. Во втором случае вы не можете изменить x *, но вы можете изменить x. Например, второй может использоваться для перехода через массив (например, с x ++), а первый не мог. –

5

В этом примере рассматривается в явном виде в разделе разрешения перегрузки, 13.1/3B4:

декларации параметров, которые отличаются только в присутствии или в отсутствии сопзЬ и/или летучие являются эквивалентны. То есть, const и volatile спецификаторы типов для каждого типа параметра игнорируются при определении, какая функция объявляется, определяется или вызывается.

[Пример:

typedef const int cInt; 
int f (int); 
int f (const int); // redeclaration of f(int) 
int f (int) { ... } // definition of f(int) 
int f (cInt) { ... } // error: redefinition of f(int) 

-end пример]

Таким образом, это, безусловно, в порядке.