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

最初に知っておくべきことは、テンプレートコンストラクターは決してコピーコンストラクターではないということです。2つ目は、aや。のように無関係な、無関係なクラスがどこにRect<T>あるかということです。Rect<U>T != Ustd::stringstd::vector

widthとにアクセスするための何らかの方法を提供する必要がheightあり、変換コンストラクターはそのようなアクセスメソッドを使用して新しいを作成する必要がありますRect

于 2012-06-12T17:15:11.250 に答える
3

K-ballo が述べたように、Rect<int>Rect<float>は異なるタイプであり、互いのプライベートおよび保護されたメンバーにアクセスできません。次のテンプレート フレンド宣言をクラスに追加することで、これを明示的に許可できます ( so のように)。

template <typename U> friend class Rect;

意味的には、これは「任意の typeUに対して、クラスにプライベートおよび保護されたメンバーへのアクセスを許可する」ことを意味します。これは、すべてのインスタンス化から他のすべてのインスタンス化へRect<U>の送信許可の付与です。RectRect

widthandのアクセサーを追加する場合 (K-ballo が示唆するように)、これは必要ないことに注意してくださいheight。変換コンストラクターでこれらのアクセサーを使用するだけで、フレンド定義を完全に放棄できます。私よりも彼の解決策を好むでしょう。私は単に別の可能なオプションとして、あなたがよく知らないかもしれない概念 (友人、特にテンプレートの友人) を紹介するために、私のものを与えます。

于 2012-06-12T17:26:03.587 に答える