传承与朋友:安全机制?

Inheritance and Friends: Safety mechanism?

我遇到了一个有趣的理论,我想知道 c++ 中是否有针对此的安全机制。

class Base
{
 private:
 virtual void a(){};
 friend class C;
}

class Derived: public Base
{
void a() override {};
}

class C{

public doSomething(const Base& b) {b.a();};

}

所有这些都是合法的 - class C 是 base 的友元,因此可以调用 b.a()。然而,当它接收到一个引用时,它可以接收到一个 Derived 对象的引用,因此 C 将访问 class Derived 中的私有区域,而不是 derived.

的朋友。

这仅仅是糟糕的代码设计,还是有防范措施?当覆盖 operator<< 并从内部调用通用打印函数时发生在我身上(操作员是 base 的朋友)。

这里不需要任何保护措施。这就是 C++ 设计的工作方式。

通过覆盖基 class 中的虚函数,派生的 class 重新实现了它。但是 "reimplementing" 的定义包括从基础 class 继承所有的包袱。包括基础 class 中的虚函数在这种情况下是 public.

派生的 class 将重新实现的函数定义为 private 这一事实不会改变它重写 public 函数的事实。因此,它应该期望它仍然可以通过基础 class.

访问

最多,我想,你可以称之为"quirk"。最重要的是,如果您要覆盖 public 虚函数,则覆盖过程不会改变它是 public 函数的事实。在派生的 class 中创建覆盖函数 "private" 是在马匹离开后关闭谷仓。

而且您必须意识到您正在覆盖 public 虚函数这一事实。在某些情况下,我会说这甚至可以成为一项功能。不难想象这样一种情况,即特定基 class 函数只能由直接引用基 class 的现有代码调用。任何具有指向派生 class 的指针或引用的代码都是更高级别的代码,不应有任何业务调用基 class 的函数。当然,这是一种方法。这当然不是某种严格的安全性,而只是编译器帮助您捕获逻辑或功能错误或某种设计错误的机制。

嗯,不,这不是 C++ 的糟糕设计。你的程序设计不好。

一个类似

的程序
 some_C.doSomething(some_derived);

将无法编译。这是因为你的 BaseDerived 的私人基地。所以 Derived &Base & 的转换是无效的。

上述情况的例外情况是执行此操作的调用函数是 Derived 的成员或 friend。在那种情况下,行为由Derived的(开发者)控制,如果你做了这样的事情,那完全是你的责任。

作为(Base 和 Derived)设计的骨架,这是 Herb Sutter 15 years ago 提倡的典型的好设计 - 除了让 class C 成为朋友是多余的,因为它可以调用 public 函数 运行()。只有当 C 只需要使用 a() 时,它才需要成为友元,以防 运行() 有更多的功能需要避免(我怀疑在这种情况下设计不好)。 我想知道我的阅读有什么问题,因为与前面的答案不同,我没有看到 a() 是 public,也没有看到 Base 是私有基地。 享受