2

我有一个带有转换构造函数的模板类 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

我想在不使用模板专业化和结交朋友类的情况下解决这个问题。据我所知,您不能将构造函数声明为朋友。有任何想法吗?

编辑:我已经对语义进行了更正。所以我试图构建的构造函数实际上是一个转换构造函数。

Edit2:更正了程序。

4

2 回答 2

4

您应该知道的第一件事是模板构造函数永远不是复制构造函数。第二件事是不同的不相关的类在哪里,就像 aRect<T>和an一样不相关。Rect<U>T != Ustd::stringstd::vector

您应该提供一些访问widthand的方法height,并且您的转换构造函数应该使用这种访​​问方法来创建新的Rect.

于 2012-06-12T17:15:11.250 回答
3

正如 K-ballo 所提到的,Rect<int>并且Rect<float>是不同的类型,并且无法访问彼此的私有成员和受保护成员。您可以通过将以下模板朋友声明添加到您的类中来明确允许这一点(就像这样):

template <typename U> friend class Rect;

从语义上讲,这意味着“对于任何类型U,让类Rect<U>访问我的私有成员和受保护成员”——它是从每个Rect实例化到每个其他Rect实例化的传出权限授予。

width请注意,如果您为and添加访问器(正如 K-ballo 建议的那样),这将不是必需height的 - 然后您可以在转换构造函数中使用这些访问器并完全放弃朋友定义。我更喜欢他的解决方案而不是我的解决方案;我给我的只是作为另一种可能的选择,并向您介绍一个您可能不熟悉的概念(朋友,特别是模板朋友)。

于 2012-06-12T17:26:03.587 回答