在寻找二叉树实现的示例时,我注意到提供的代码here中有些奇怪。在 Node 结构的构造函数中,非指针类型变量被赋值给指针类型。
它编译得很好(我正在使用GCC 5.3.0)。让我感到困惑的是编译依赖于其他构造函数的参数 val 。
它对类方法没有影响,只在构造函数中有效:
template <typename T>
class Test {
Test* testPtr;
void testMethod(T t, Test<T> notAPointer) { // OK
this->testPtr = notAPointer;
}
void testMethod(Test<T> notAPointer) { // OK
this->testPtr = notAPointer;
}
Test(T t, Test<T> notAPointer) { // OK
this->testPtr = notAPointer;
}
Test(Test<T> notAPointer) { // compilation error
this->testPtr = notAPointer;
}
};
我得到的编译错误是:
无效的构造函数;你可能意味着'测试(const测试&amp;)'
为什么会这样?标准中的这种行为描述在哪里?
答案 0 :(得分:3)
您的上一个构造函数是copy constructor。禁止有一个复制构造函数按值传递它的参数,否则你最终会得到无限递归。
您获得的错误类似于
struct Foo
{
Foo(Foo);
};
更确切地说,根据标准:
12.8 / 2复制和移动类对象[class.copy]
如果第一个参数的类型为
X
,X&
,const X&
或volatile X&
,则类const volatile X&
的非模板构造函数是一个复制构造函数,并且没有其他参数,或者所有其他参数都有默认参数(8.3.6)。 [例如:X::X(const X&)
和X::X(X&,int=1)
是复制构造函数。
其他构造函数/成员函数似乎没问题,因为它们没有实例化,并且代码在语法上是正确的(理论上,Test<T>
可能有一个转换运算符T*
用于某些特化,并且编译器在实例化之前无法检查)。但是,复制构造函数必须具有明确的形式,由编译器强制执行。
答案 1 :(得分:1)
您的所有示例均无效。当您尝试实例化任何方法时,您将收到编译器错误:
template <typename T>
struct Test {
Test* testPtr;
void testMethod(Test<T> notAPointer) {
this->testPtr = notAPointer;
}
};
int main() {
Test<int> t1, t2;
t1.testMethod(t2); // This line will cause the error.
return 0;
}
prog.cpp:实例化'void Test :: testMethod(Test)[with T = int]':prog.cpp:16:18:从这里需要prog.cpp:9:23:错误: 无法在分配中将“测试”转换为“测试*” this-&gt; testPtr = notAPointer; ^