如何对除 T 类之外的所有人隐藏基准面



我想要一个类型 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;
}

顺便说一下,这工作正常,除了它无法隐藏基准面:

#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++真的不允许在编译时将友元类指定为模板参数吗? 为什么不呢? 如果不是,那么我应该使用什么替代技术来隐藏基准面? (如果可能的话,人们更喜欢编译时技术。

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

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

谢谢。

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

§11.3 [class.friend] p3

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

  • friend elaborated-type-specifier ;
  • friend simple-type-specifier ;
  • friend typename-specifier ;

如果 friend 声明中的类型说明符指定了一个(可能符合 cv 的(类类型,则该类被声明为 friend;否则,将忽略 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 没有办法做到这一点,但是您可以简单地与单个自由函数交朋友,并让它充当"胶水"代码,从一个类中获取数据并将其传递给另一个类。另一种方式可能是密钥模式。

我不知道

您的错误背后的标准(请参阅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;
}

最新更新