与朋友声明相反

Opposite of friend declaration

本文关键字:声明 朋友      更新时间:2023-10-16

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

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的对象,但其他类可以访问(因为它是public(。

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

这样的结构是否可行,还是我坚持保持Foo私密并为所有课程添加朋友?

这样的事情是不存在的,而且是极其没有意义的。想象一下,您遇到这样的情况:

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

这真的做不到,但也许以下对你来说就足够了:

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.
}
};

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

公共属性将始终是公共的,但您可以通过保护构造函数来限制Foo的公开,例如,并且仅对选定的类可见(尽管建议限制friend(。也许也可以Foo作为受保护的Bar2类,因为只有Bar2或其子代才会真正使用它。

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

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

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