朋友宣言对面

Som*_*ken 6 c++ friend c++17

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

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

class Bar
{
  Bar()
  {
    //create a Foo object
  }
};
Run Code Online (Sandbox Code Playgroud)

现在如果我想要相反的friend,Foo看起来像这样:

class Foo
{
 //enemy/foe??? class Bar; (if only)
public:
  Foo();
};
Run Code Online (Sandbox Code Playgroud)

然后没有方法Bar可以访问Foo构造函数/使Foo其他类的对象可以(因为它是public).

class Bar
{
  Bar()
  {
    Foo foo; //compiler error
  }
};
Run Code Online (Sandbox Code Playgroud)

这样的构造是可能的还是我坚持保持Foo私密并为所有类添加朋友?

Rei*_*ica 8

这样的事情不存在,而且非常没有意义.想象一下你有这样的情况:

class Foo
{
  enemy class Bar;

public:
  Foo() {}
};

class Bar
{
  void evil() { Foo{}; }
};
Run Code Online (Sandbox Code Playgroud)

没有什么能阻止实现者Bar这样做:

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

void do_evil(Bar &self)
{
  Foo{};
}
Run Code Online (Sandbox Code Playgroud)

do_evil不是Bar(它是一个全局函数)的成员,因此它不是敌人.因此可以琐碎地规避这种不友善.

  • 公平地说,`#define private public`也是一种方式:P.`const_cast`也是一个肮脏的黑客.对我而言,这并不是说100%确定无论你怎么努力都不能制作一个`Foo`对象,它更倾向于在方法中发出编译器错误,所以客户端知道他们可能做错了什么搞错了在`Bar`里面``Foo`因此不应该试图绕开它. (4认同)

Jar*_*d42 1

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

template <typename T> struct Tag {};

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

    Foo(Tag<Bar>) = delete;

    // ...
};
Run Code Online (Sandbox Code Playgroud)

因此要求“创造者”“识别”自己。

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

        // Foo foo{Tag<void>{}}; // valid as we can cheat about identity.
    }
};
Run Code Online (Sandbox Code Playgroud)