我有一个带有转换构造函数的模板化类Rect,它允许在Rect和Rect之间进行转换,反之亦然。但是在编译代码时,编译器会给出一个错误,指出构造函数无法访问类的受保护成员。 这是代码:
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
template< typename T >
class Rect{
protected:
T width, height;
public:
Rect(T a, T b){
width = a;
height = b;
}
template< typename U >
Rect(Rect<U> const &r){
width = r.width;
height = r.height;
}
int area(){
return width*height;
}
};
int main(){
Rect<int> a(3,4);
Rect<float> b(a);
cout<<b.area()<<endl;
}
这是编译错误:
test.cpp: In constructor ‘Rect<T>::Rect(const Rect<U>&) [with U = int, T = float]’:
test.cpp:28:18: instantiated from here
test.cpp:10:7: error: ‘int Rect<int>::width’ is protected
test.cpp:18:5: error: within this context
test.cpp:10:14: error: ‘int Rect<int>::height’ is protected
test.cpp:19:5: error: within this context
我想在不使用模板专业化和制作朋友类的情况下解决此问题。据我所知,你不能将构造函数声明为朋友。有什么想法吗?
编辑:我对语义进行了更正。所以我试图构建的构造函数实际上是一个转换构造函数。
编辑2:更正了该计划。
答案 0 :(得分:4)
您应该知道的第一件事是模板构造函数永远不是复制构造函数。第二件事是Rect<T>
和Rect<U>
其中T != U
是不同的无关类,与std::string
和std::vector
无关。
您应该提供一些方法来访问width
和height
,而您的转换构造函数应该使用此类访问方法来创建新的Rect
。
答案 1 :(得分:3)
正如K-ballo所提到的,Rect<int>
和Rect<float>
是不同的类型,并且无法访问彼此的私人和受保护成员。您可以通过向类(like so)添加以下模板好友声明来明确允许此操作:
template <typename U> friend class Rect;
从语义上讲,这意味着“对于任何类型U
,为类Rect<U>
提供对我的私有和受保护成员的访问权限” - 这是从每个Rect
实例化到的传出权限授予每隔一个Rect
实例化。
请注意,如果您为width
和height
添加访问器(如K-ballo建议的那样),则无需执行此操作 - 然后您可以在转换构造函数中使用这些访问器并放弃朋友定义完全。我宁愿他的解决方案超过我的;我只是作为另一种可能的选择给我,并向你介绍一个你可能不熟悉的概念(朋友,特别是模板朋友)。