Несоответствие между определением конструктора и объявлением

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

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

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

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

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


person MikeT    schedule 01.04.2009    source источник


Ответы (4)


В подобных случаях спецификатор 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 int * const, это будет иметь значение, потому что для вызывающей стороны имеет значение, если вы измените данные, на которые он указывает.

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

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

person Brian R. Bondy    schedule 01.04.2009
comment
Пожалуйста, дайте ссылку на Стандарт. - person Mykola Golubyev; 01.04.2009
comment
я написал об этом здесь, если вам нужно больше примеров: stackoverflow .com / questions / 269882 / c-const-question /. - person Johannes Schaub - litb; 01.04.2009
comment
@ onebyone.livejournal.com: Спасибо. - person Brian R. Bondy; 01.04.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 для каждого типа параметра игнорируются при определении, какая функция объявляется, определяется или вызывается. [Пример:

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 example] Таким образом игнорируются только спецификаторы типа const и volatile на самом внешнем уровне спецификации типа параметра; Спецификаторы типа const и volatile, скрытые в спецификации типа параметра, имеют важное значение и могут использоваться для различения объявлений перегруженных функций.112) В частности, для любого типа T, «указатель на T», «указатель на const T» и «указатель» to volatile T »считаются отдельными типами параметров, как и« ссылка на T »,« ссылка на const T »и« ссылка на volatile T. »

person Eclipse    schedule 01.04.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)

—Конечный пример]

Так что это определенно нормально.

person Richard Corden    schedule 01.04.2009

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

person Community    schedule 01.04.2009
comment
Нет. В первом случае x является константным указателем на константное целое число. Во втором случае x - это указатель non-const на целое число const. - person Luc Touraille; 01.04.2009
comment
В частности, вы не можете изменять ни x, ни x. Во втором случае вы не можете изменить x, но можете изменить x. Например, второй может использоваться для обхода массива (например, с x ++), а первый - нет. - person David Thornley; 01.04.2009