C++,将非指针类型赋值给模板的成员指针 class
C++, assignment of non-pointer type to a member pointer of template class
在寻找二叉树实现的示例时,我注意到提供的代码中有些奇怪的地方 here。在 Node 结构的构造函数中,一个非指针类型变量被分配给一个指针类型。
它编译得很好(我使用的是 GCC 5.3.0)。让我真正困惑的是编译依赖于其他构造函数的参数,val.
它在 class 方法中没有效果,仅在构造函数中有效:
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;
}
};
我得到的编译错误是:
invalid constructor; you probably meant ‘Test (const Test&)’
为什么会这样?标准中哪里描述了这种行为?
您的最后一个构造函数是 copy constructor。禁止有一个按值传递其参数的复制构造函数,否则你最终会无限递归。
您遇到的错误类似于
struct Foo
{
Foo(Foo);
};
更准确地说,根据标准:
12.8/2 复制和移动 class 个对象 [class.copy]
A non-template constructor for class X
is a copy constructor if its first parameter is of type X&
, const X&
, volatile X&
or const volatile X&
, and either there are no other parameters or else all other parameters have default arguments (8.3.6). [ Example: X::X(const X&)
and X::X(X&,int=1)
are copy constructors.
其他的 constructors/member 函数看起来没问题,因为它们没有被实例化,而且代码在语法上是正确的(理论上,Test<T>
可能有一个到 T*
的转换运算符用于某些特殊化,并且编译器无法在实例化之前对其进行检查)。然而,复制构造函数必须具有明确的形式,这是由编译器强制执行的。
你所有的例子都是无效的。当您尝试 实例化 任何方法时,您将遇到编译器错误:
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: In instantiation of 'void Test::testMethod(Test) [with
T = int]': prog.cpp:16:18: required from here prog.cpp:9:23: error:
cannot convert 'Test' to 'Test*' in assignment
this->testPtr = notAPointer;
^
在寻找二叉树实现的示例时,我注意到提供的代码中有些奇怪的地方 here。在 Node 结构的构造函数中,一个非指针类型变量被分配给一个指针类型。
它编译得很好(我使用的是 GCC 5.3.0)。让我真正困惑的是编译依赖于其他构造函数的参数,val.
它在 class 方法中没有效果,仅在构造函数中有效:
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;
}
};
我得到的编译错误是:
invalid constructor; you probably meant ‘Test (const Test&)’
为什么会这样?标准中哪里描述了这种行为?
您的最后一个构造函数是 copy constructor。禁止有一个按值传递其参数的复制构造函数,否则你最终会无限递归。
您遇到的错误类似于
struct Foo
{
Foo(Foo);
};
更准确地说,根据标准:
12.8/2 复制和移动 class 个对象 [class.copy]
A non-template constructor for class
X
is a copy constructor if its first parameter is of typeX&
,const X&
,volatile X&
orconst volatile X&
, and either there are no other parameters or else all other parameters have default arguments (8.3.6). [ Example:X::X(const X&)
andX::X(X&,int=1)
are copy constructors.
其他的 constructors/member 函数看起来没问题,因为它们没有被实例化,而且代码在语法上是正确的(理论上,Test<T>
可能有一个到 T*
的转换运算符用于某些特殊化,并且编译器无法在实例化之前对其进行检查)。然而,复制构造函数必须具有明确的形式,这是由编译器强制执行的。
你所有的例子都是无效的。当您尝试 实例化 任何方法时,您将遇到编译器错误:
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: In instantiation of 'void Test::testMethod(Test) [with T = int]': prog.cpp:16:18: required from here prog.cpp:9:23: error: cannot convert 'Test' to 'Test*' in assignment this->testPtr = notAPointer; ^