Mismatch between constructor definition and declaration

巧了我就是萌 提交于 2019-12-10 14:10:23

问题


I had the following C++ code, where the argument to my constructor in the declaration had different constness than the definition of the constructor.

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

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

I was able to compile this with no warnings using g++, should this code compile or at least give some warnings? It turns out that the built-in C++ compiler on 64 bit solaris gave me a linker error, which is how I noticed that there was an issue.

What is the rule on matching arguments in this case? Is it up to compilers?


回答1:


In cases like this, the const specifier is allowed to be ommitted from the declaration because it doesn't change anything for the caller.

It matters only to the context of the implementation details. So that's why it is on the definition but not the declaration.

Example:

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

Anyone calling f won't care that you are going to treat it as const because it is your own copy of the variable.

With int * const x, it is the same, it is your copy of the pointer. Whether you can point to something else doesn't matter to the caller.

If you ommitted the first const though in const int * const, then that would make a difference because it matters to the caller if you change the data it is pointing to.

Reference: The C++ Standard, 8.3.5 para 3:

"Any cv-qualifier modifying a parameter type is deleted ... Such cv-qualifiers affect only the definition of the parameter with the body of the function; they do not affect the function type"




回答2:


This example is covered explicitly in the overload resolution section, 13.1/3b4:

Parameter declarations that differ only in the presence or absence of const and/or volatile are equivalent. That is, the const and volatile type-specifiers for each parameter type are ignored when determining which function is being declared, defined, or called.

[Example:

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]

So, it is definitely OK.




回答3:


Think of it as the same difference between

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

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

Which also compiles. You can't overload based on the const-ness of a pass-by-value parameter. Imagine this case:

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

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

From the standard:

Parameter declarations that differ only in the presence or absence of const and/or volatile are equivalent. That is, the const and volatile type-specifiers for each parameter type are ignored when determining which function is being declared, defined, or called. [Example:

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] Only the const and volatile type-specifiers at the outermost level of the parameter type specification are ignored in this fashion; const and volatile type-specifiers buried within a parameter type specification are significant and can be used to distinguish overloaded function declarations.112) In particular, for any type T, “pointer to T,” “pointer to const T,” and “pointer to volatile T” are considered distinct parameter types, as are “reference to T,” “reference to const T,” and “reference to volatile T.”




回答4:


Is const int * const x not the same like const int * x becouse u already maked const?



来源:https://stackoverflow.com/questions/706059/mismatch-between-constructor-definition-and-declaration

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!