如何对所有人隐藏自己,但T类

问题描述:

基准我想要一个类型一个,将产生其隐藏的数据来类型T的对象,但隐藏其他人的数据。我的C++编译器恰好是GCC 4.4,但这并不重要。为什么这不工作?如何对所有人隐藏自己,但T类

#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; 
} 

顺便说一句,这工作得很好,但它无法隐藏基准:

#include <iostream> 

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

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

int main() { 
    const A<B> a(5); 
    const B b; 
    const int m = b.f(a); 
    std::cout << m << "\n"; 
    return 0; 
} 

不C++真的不能让一个朋友类在编译时作为模板参数来指定?为什么不?如果不是,那么我应该使用什么替代技术来隐藏数据? (如果可能的话,人们更喜欢编译时技术。)

请问我在这里有什么误解?我看到一些相关问题的答案herehere,但是他们没有回答我的问题,或者我没有理解他们这样做。无论如何,也许我完全使用了错误的技术。仍然有兴趣为什么朋友类T失败,我真正想知道的是如何隐藏数据,无论是与朋友还是其他方式。)

谢谢。

我不知道你的错误背后的标准(参考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; 
} 

或者,您也可以使T的嵌套类/结构是A的朋友,这可能是如果您希望T有权访问A的几个私人成员,则更方便。

#include <iostream> 

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

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

class C { 
    public: 
    int f(const A<B> a) const { return AccessToA::getN1(a); } 
    C() {}; 

    private: 
    friend class A<C>; 
    struct AccessToA 
    { 
     // Error, n1 is a private member of A<B> 
     static int getN1(const A<B>& a) {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; 
} 
+0

很好的建议。除非我能提出更好的建议,否则我应该听取建议。谢谢。 – thb 2012-03-17 22:45:43

你的编译器太旧了。 C++ 11允许你将模板参数声明为朋友。

§11.3 [class.friend] p3

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

  • friendelaborated-type-specifier;
  • friendsimple-type-specifier;
  • friendtypename-specifier;

如果在一个friend声明类型说明符指定一个(可能是CV-合格)类型,即类被声明为friend;否则,朋友声明被忽略。

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

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++ 03可悲的是有没有办法做到这一点,但是你可以简单的朋友一个免费的功能,让它充当“粘合”代码,从一个类获取数据并将其传递给另一个类。另一种方式可能是passkey pattern

+0

我明白了。谢谢。也感谢您的照明密钥链接。 – thb 2012-03-17 22:44:08