代码之家  ›  专栏  ›  技术社区  ›  Hatted Rooster

朋友宣言的反面

  •  6
  • Hatted Rooster  · 技术社区  · 6 年前

    friend

    class Foo
    {
     friend class Bar;
    private:
      Foo();
    };
    
    class Bar
    {
      Bar()
      {
        //create a Foo object
      }
    };
    

    如果我想要相反的结果呢 朋友 ,在哪里 Foo 看起来像这样:

    class Foo
    {
     //enemy/foe??? class Bar; (if only)
    public:
      Foo();
    };
    

    然后就没有办法 Bar 构造器 但是其他类可以(因为它是 public ).

    class Bar
    {
      Bar()
      {
        Foo foo; //compiler error
      }
    };
    

    4 回复  |  直到 6 年前
        1
  •  1
  •   Jarod42    6 年前

    这是不可能做到的,但也许以下几点对你来说就足够了:

    template <typename T> struct Tag {};
    
    class Foo
    {
    public:
        template <typename T>
        Foo(Tag<T>) {}
    
        Foo(Tag<Bar>) = delete;
    
        // ...
    };
    

    class Bar
    {
        Bar()
        {
            Foo foo{Tag<Bar>{}}; //compiler error
    
            // Foo foo{Tag<void>{}}; // valid as we can cheat about identity.
        }
    };
    
        2
  •  8
  •   Angew is no longer proud of SO    6 年前

    这样的事情是不存在的,而且是毫无意义的。想象一下你有这样的情况:

    class Foo
    {
      enemy class Bar;
    
    public:
      Foo() {}
    };
    
    class Bar
    {
      void evil() { Foo{}; }
    };
    

    Bar 这样做:

    class Bar
    {
      void evil() { do_evil(*this); }
    };
    
    void do_evil(Bar &self)
    {
      Foo{};
    }
    

    do_evil 不是的成员 (这是一个全球性的功能),所以它不是敌人。因此,这种不友好的态度是可以轻易避免的。

        3
  •  0
  •   Matthieu Brucher    6 年前

    Foo 例如,通过使构造函数受保护,并且仅对选定的类可见(尽管限制 friend 作为一个受保护的 Bar2 酒吧2

        4
  •  0
  •   Handy999    6 年前

    正如其他人已经说过的,你的欲望打破了封装的概念,因为你不可能总是知道你的敌人是谁。

    #include <type_traits>
    
    struct enemy;  // We need a forward declaration of your enemy
    
    struct my_class {
    
        // The access is done using a factory, where the caller has to tell
        // us his own name
        template <class T>
        struct make{
            static_assert(!std::is_same<T,enemy>::value,"you are my enemy.");
            friend T;
        private:
            my_class operator() () { return my_class{}; }
        };
    
    
    private:
        my_class(); // This is the constructor we care about
    
    };
    
    struct no_enemy {
        void bar() {
            my_class a = my_class::make<no_enemy>{}();  // works
        }
    };
    
    
    struct enemy {
        void bar() {
            my_class b = my_class::make<enemy>{}();     // error: static_assert failed
            my_class c = my_class::make<no_enemy>{}();  // error: foo is "private"
        }
    };