gpt4 book ai didi

c++ - 友好性和访问级别的继承

转载 作者:太空狗 更新时间:2023-10-29 22:58:14 25 4
gpt4 key购买 nike

我有以下测验问题:

#include <iostream>
using namespace std;

struct A
{
void ohai() { cout << "ohai" << endl; }
};

struct C : private A {
friend int main();
};

struct X : C {};
struct Y : private C {};

int main() {
C().ohai() // OK
X().ohai(); // OK
Y().ohai(); // Not OK
}

问题是 C 类私自继承自 A。因此,A 的所有成员,甚至是公共(public)成员,现在在 C 中都变成了私有(private)成员。C 类还声明了与 main 函数的友好性(这没关系,现在“main”函数可以调用 C 的私有(private)方法)。然后是类 X 和 Y,它们都派生自 C。X 公开派生自 C,Y 私下派生自 C。

在“main”函数中,我创建了类 C 的实例并调用了从 A 私有(private)继承的“ohai”方法,这工作正常,因为 main 是 C 的友元。然后我创建类 X 的实例并调用“ohai”——这出人意料地有效!但是当我创建 Y 类的实例时,这不起作用!

我知道继承是不可继承的。所以这不是允许'main'在类X的对象上调用'ohai'方法的友好性继承。Y 类的事情证实了这一点,因为将继承类型更改为私有(private)就足以停止此工作。

我想知道为什么可以在 X 对象上调用“ohai”。继承不能提升函数的级别(从私有(private)到公共(public)),所以如果 X 从 C 继承,即使是公开的,所有来自 C 的私有(private)方法在 X 中都应该保持私有(private)。并且由于友好性不可继承,“main”方法不应该能够调用 X 的私有(private)方法。Y 类从 C 私有(private)继承,这使得 C 的所有成员在 X 中都是私有(private)的,但是 'ohai' 方法在 C 中已经是私有(private)的(因为 C 从 A 私有(private)继承)所以这不应该改变任何东西,但不知何故它确实(与 X 相比)。

请帮助我理解这个问题。最好的祝福优凯

最佳答案

我不完全确定我在这里的回答。如果我错了,请纠正我。

我相信这里发生的是,当您调用 X().ohai() 时,X 中的 this 指针是隐式的转换为其基类 C,它授予 main 友元。更准确地说,当编译器在 X 中寻找 ohai 时,它没有在 X 中找到它,也没有在它的直接基类 C 中找到它,而是在 A 中找到它。友元和其他访问控制机制不会干扰编译器应该在哪里找到成员函数。找到成员后才会生效。一旦编译器在 A 中找到了 ohai,它需要将一个 X * 指针(this)转换为 A *。 (到目前为止,我很确定我是正确的)。 X 是 public 继承自 C 的,因此它可以将其转换为 C *。而C给了main友情,所以它可以继续把它投给A *。因此它能够调用 ohai。 (最后一部分不是很精确,但更容易理解)。

例如,尝试以下操作,

int main()
{
X x;
Y y;
static_cast<A *>(&x);
static_cast<A *>(&y);
}

第一次转换没有问题,而第二次转换会在 Clang 中出现以下错误,

test.cpp:24:22: error: cannot cast 'Y' to its private base class 'A'
static_cast<A *>(&y);
^
test.cpp:15:11: note: constrained by private inheritance here
class Y : private C
^~~~~~~~~

如果删除 friend 声明,第一次转换也会失败,但原因不同。

“友元无法继承”是对的,但实际上与这里发生的事情没有任何关系

如果删除好友声明,并尝试以下操作,

int main()
{
X x;
Y y;
static_cast<A *>(&x);
static_cast<C *>(&x);
}

由于访问控制,第一次转换将失败,而第二次将成功。

与 main 的友元不仅授予其访问 C 的私有(private)成员的权限,还授予其私有(private)基类的访问权限。对于这个问题,在有和没有 friend 声明的情况下尝试以下操作

int main()
{
C c;
static_cast<A *>(&c);
}

最后,尝试以下操作

struct A {
void ohai() { std::cout << "ohai" << std::endl; }
};

struct C : private A {
using A::ohai;
};

struct X : C {
void foo() { C::ohai(); } // static_cast<C *>(this)->ohai();
void bar() { A::ohai(); } // static_cast<A *>(this)->ohai();
};

int main()
{
X x;
x.foo();
x.bar();
x.ohai();
}

函数 foo 可以,但是 bar 会失败。因为 X 可以转换为其直接基数 C 并调用在 C 中公开的 ohai。但是不能对A进行大小写调用A

中的 ohai

关于c++ - 友好性和访问级别的继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41075320/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com