我有以下C ++代码,其中声明中构造函数的参数与构造函数的定义具有不同的常量。
//testClass.hpp
class testClass {
public:
testClass(const int *x);
};
//testClass.cpp
testClass::testClass(const int * const x) {}
我能够使用g ++编译这个没有警告,如果这段代码编译或至少给出一些警告?事实证明,64位solaris上的内置C ++编译器给了我一个链接器错误,这就是我注意到存在问题的方式。
在这种情况下匹配参数的规则是什么?这取决于编译器吗?
答案 0 :(得分:7)
在这种情况下,允许从声明中省略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中省略了第一个const,那么这会有所不同,因为如果你改变它所指向的数据,它对调用者很重要。
参考: C ++标准,8.3.5第3段:
“任何cv-qualifier修改 参数类型被删除...这样 cv-qualifiers只影响 使用的定义参数 身体的功能;他们不 影响功能类型“
答案 1 :(得分:5)
此示例在重载解析部分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)
-end example]
所以,这绝对没问题。
答案 2 :(得分: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是等价的。 也就是说,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的类型说明符 参数类型的最外层 规范在此被忽略 时尚;常量和不稳定 埋藏在一个中的类型说明符 参数类型规范是 重要的,可以用来 区分重载功能 声明.112)特别是, 对于任何类型T,“指向T的指针” “指向const T的指针”和“指向 挥发性T“被认为是不同的 参数类型,“参考 T,“”引用const T,“和 “提到挥发性T。”
答案 3 :(得分:0)
const int * const x
与const int * x
不一样,因为你已经制作了const?