Maison > Questions et réponses > le corps du texte
如下面的这段代码所示,模板类里面有一个模板成员函数,其中有问题的地方我已经标注了,就是注释的那一行。请问为什么要用getValue()这个成员函数啊,如果没有main函数里面的语句,用x.value()是可以编译通过的,但是因为有了main()里面的语句,就必须要用个成员函数才行,这是为什么啊?
#include <iostream>
template<typename T>
class MyClass
{
private:
T value;
public:
/*void assign(const MyClass<T>& x)
{
value = x.value;
}*/
template <typename X>
void assign(const MyClass<X>& x)
{
value = x.value; //这里有问题,要用getValue()才对。
}
const T& getValue() const
{
return value;
}
};
int main()
{
MyClass<double> d;
MyClass<int> i;
d.assign(d);
d.assign(i);
return 0;
}
伊谢尔伦2017-04-17 13:28:52
模板类在编译时会根据使用情况实例化成具体的类。
例如模板MyClass<T>
在main
中使用了不同的两个实例,则会实例化成MyClass<double>
和MyClass<int>
两个类,这两个类虽然是由同一个模板生成的,但他们是两个不同的类,没有友元关系,不能互相访问私有成员。
template<typename T>
class MyClass
{
private:
T value;
public:
/* ... */
template <typename X>
void assign(const MyClass<X>& x)
{
value = x.value; // 1. 当类型 X 与 T 相同时,则为同一个类,可以访问自己的私有成员
// 当类型 X 与 T 不同时,则不是同一个类,不能访问对方的私有成员
}
const T& getValue() const
{
return value;
}
};
int main()
{
MyClass<double> d;
MyClass<int> i;
d.assign(d); // 2. X 与 T 相同,正常编译运行
d.assign(i); // 3. X 与 T 不同,编译报错
return 0;
}
与模板相关的错误通常很难在编译时查出,你可以把上述3
的语句注释掉,就能正常编译运行了,但是如果想使3
的语句能编译运行,就需要通过getValue
成员来访问私有成员,使得T
与X
在实例化为不同类型时仍能运行。
另外,1
处的语句使用了operator=
进行赋值,则对MyClass<T>
模板的类型T
提出了一个潜在的要求,即类型T
存在operator=
参数可由类型X
转化而得。
迷茫2017-04-17 13:28:52
模板类是在编译时根据不同的特化生成不同的代码的。x.value
使用了x的私有属性当然会报错,成员函数(setter
和getter
)提供接口不是很正常吗...
如果没有main
函数里的东西,编译器就不会生成MyClass<double>
和MyClass<int>
,只要模板类里没有语法错误就行。
ps.我把value = x.value;
改成value = x.vvvvvv;
,clang和g++都编译通过了233