如何隐藏除T类之外的所有人的数据

thb*_*thb 5 c++ templates information-hiding friend 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:
    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;
}
Run Code Online (Sandbox Code Playgroud)

顺便说一下,这样可以正常工作,除了它无法隐藏数据:

#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;
}
Run Code Online (Sandbox Code Playgroud)

C++是否真的不允许在编译时将友元类指定为模板参数?为什么不?如果没有,那么我应该使用什么替代技术来隐藏基准?(如果可能,人们更喜欢编译时技术.)

请问我在这里有什么误解?

(我在这里这里看到了相关问题的一些答案,但要么他们没有回答我的特定问题,要么我不理解他们这样做.无论如何,也许我完全使用错误的技术.虽然我仍然感兴趣为什么朋友级T失败了,我真正想知道的是如何隐藏数据,无论是与朋友还是通过其他方式.)

谢谢.

Emi*_*ier 1

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

或者,您可以使 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;
}
Run Code Online (Sandbox Code Playgroud)