C++ 如何对T类以外的所有人隐藏数据

C++ 如何对T类以外的所有人隐藏数据,c++,templates,friend,information-hiding,access-protection,C++,Templates,Friend,Information Hiding,Access Protection,我想要一个类型a,它会将其隐藏的数据提供给类型T的对象,但对其他所有人隐藏该数据。我的C++编译器恰好是GCC 4.4,但这不重要。为什么这样不行 #include <iostream> template <class T> class A { private: int n1; public: friend class T; A(const int n0 = 0) : n1(n0) {} }; class B { public:

我想要一个类型a,它会将其隐藏的数据提供给类型T的对象,但对其他所有人隐藏该数据。我的C++编译器恰好是GCC 4.4,但这不重要。为什么这样不行

#include <iostream>

template <class T> class A {
  private:
    int n1;
  public:
    friend class T;
    A(const int n0 = 0) : n1(n0) {}
};

class B {
  public:
    int f(const A<B> a) const { return a.n1; }
    B() {}
};

int main() {
    const A<B> a(5);
    const B b;
    const int m = b.f(a);
    std::cout << m << "\n";
    return 0;
}
#包括
模板类别A{
私人:
int-n1;
公众:
朋友级T;
A(常数int n0=0):n1(n0){}
};
B类{
公众:
intf(常数A)常数{返回A.n1;}
B(){}
};
int main(){
常数A(5);
常数B;
常数int m=b.f(a);

我不知道你的错误背后的标准(参考Xeo的答案),但我确实找到了C++03的解决方法。 与其让
T
成为朋友,不如让
T
的一个成员函数成为朋友:

#include <iostream>

template <class T> class A {
  private:
    int n1;
  public:
    friend int T::getN1(const A& a) const;
    A(const int n0 = 0) : n1(n0) {}
};

class B {
  public:
    int f(const A<B> a) const { return getN1(a); }
    B() {}
  private:
    int getN1(const A<B>& a) const {return a.n1;}
};

class C {
  public:
    int f(const A<B> a) const { return getN1(a); }
    C() {}
  private:
    // Error, n1 is a private member of A<B>
    int getN1(const A<B>& a) const {return a.n1;}
};

int main() {
    const A<B> a(5);
    const B b;
    const int m = b.f(a);
    std::cout << m << "\n";
    return 0;
}
class C;
// [...]
template <typename T> class R {
  friend T;
};

R<C> rc;   // class C is a friend of R<C>
R<int> ri; // OK: "friend int;" is ignored
#包括
模板类别A{
私人:
int-n1;
公众:
friend int T::getN1(常量A&A)常量;
A(常数int n0=0):n1(n0){}
};
B类{
公众:
int f(常数A)常数{return getN1(A);}
B(){}
私人:
int getN1(常数A&A)常数{返回A.n1;}
};
C类{
公众:
int f(常数A)常数{return getN1(A);}
C(){}
私人:
//错误,n1是的私有成员
int getN1(常数A&A)常数{返回A.n1;}
};
int main(){
常数A(5);
常数B;
常数int m=b.f(a);

std::cout您的编译器太旧了。C++11允许您将模板参数声明为好友

§11.3[类朋友]p3

未声明函数的友元声明应具有以下形式之一:

  • friend
    详细的类型说明符
  • friend
    简单类型说明符
  • friend
    类型名称说明符
如果
友元
声明中的类型说明符指定了一个(可能是cv限定的)类类型,则该类将被声明为
友元
;否则,友元声明将被忽略

它甚至包含一个模板参数示例作为朋友:

#include <iostream>

template <class T> class A {
  private:
    int n1;
  public:
    friend int T::getN1(const A& a) const;
    A(const int n0 = 0) : n1(n0) {}
};

class B {
  public:
    int f(const A<B> a) const { return getN1(a); }
    B() {}
  private:
    int getN1(const A<B>& a) const {return a.n1;}
};

class C {
  public:
    int f(const A<B> a) const { return getN1(a); }
    C() {}
  private:
    // Error, n1 is a private member of A<B>
    int getN1(const A<B>& a) const {return a.n1;}
};

int main() {
    const A<B> a(5);
    const B b;
    const int m = b.f(a);
    std::cout << m << "\n";
    return 0;
}
class C;
// [...]
template <typename T> class R {
  friend T;
};

R<C> rc;   // class C is a friend of R<C>
R<int> ri; // OK: "friend int;" is ignored
C类;
// [...]
模板类R{
朋友T;
};
rc;//C类是R的朋友
R ri;//确定:“friend int;”被忽略

遗憾的是,C++03无法做到这一点,但是您可以简单地将一个免费函数作为朋友,并让它充当“粘合剂”从一个类中获取数据并将其传递给另一个类的代码。另一种方法可能是。

我明白了。谢谢。还感谢您提供的具有启发性的密钥链接。好建议。除非我能想出更好的方法,否则我应该按照建议进行操作。谢谢。另外,请查看Xeo建议的密钥习惯用法以及律师客户id我已经有一段时间没有读到这些了,所以我的解决方案很可能是这些习惯用法的变体。