好友声明的反面

Opposite of friend declaration

假设我们有一个具有私有构造函数的 class,通过 friend 我们可以允许某些特定的 class(es) 仍然创建此 class 的对象:

class Foo
{
 friend class Bar;
private:
  Foo();
};

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

现在如果我想要 friend 的对立面怎么办,其中 Foo 看起来像这样:

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

然后 Bar 的任何方法都不能访问 Foo 构造函数/创建 Foo 的对象,但其他 classes 可以(因为它是 public).

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

这样的构造是否可能,或者我是否坚持将 Foo 保密并为所有 class 添加好友?

这种东西是不存在的,而且是极其没有意义的。想象一下你有这样的情况:

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 不是 Bar 的成员(它是一个全局函数),所以它不是敌人。因此,可以轻松规避这种不友好。

C++中没有这样的概念。

Public 属性将始终是 public,但是您可以限制 Foo 的暴露,方法是使构造函数受保护,例如,仅对选定的 class 可见]es(尽管建议限制 friend)。也许还可以将 Foo 作为 Bar2 的受保护 class,因为只有 Bar2 或其子代会实际使用它。

确实做不到,但也许下面的内容对你来说已经足够了:

template <typename T> struct Tag {};

class Foo
{
public:
    template <typename T>
    Foo(Tag<T>) {}

    Foo(Tag<Bar>) = delete;

    // ...
};

所以向 "creator" 询问 "identify" 本身。

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

        // Foo foo{Tag<void>{}}; // valid as we can cheat about identity.
    }
};

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

但是,还是有可能得到(几乎)你想要的:

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