Несоответствие между определением конструктора и объявлением - PullRequest
5 голосов
/ 01 апреля 2009

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

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

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

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

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

Ответы [ 4 ]

7 голосов
/ 01 апреля 2009

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

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

Пример:

//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)
{
}

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

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

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

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

"Любой cv-квалификатор, модифицирующий тип параметра удален ... такой cv-квалификаторы влияют только на определение параметра с тело функции; они не влияет на тип функции "

5 голосов
/ 01 апреля 2009

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

Декларации параметров, которые отличаются только наличием или отсутствием const и / или volatile, эквивалент. То есть спецификаторы 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)

- конец примера]

Итак, это определенно нормально.

4 голосов
/ 01 апреля 2009

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

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

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

Что также компилируется. Вы не можете перегружать, основываясь на постоянстве параметра передачи по значению. Представьте себе этот случай:

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

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

Из стандарта:

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

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)

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

0 голосов
/ 01 апреля 2009

Разве const int * const x не совпадает с const int * x, потому что вы уже сделали const?

...