【问题标题】:Why a friend class member can access a private member of the class it is being friend to through an object of publicly inherited class?为什么朋友类成员可以通过公共继承类的对象访问它成为朋友的类的私有成员?
【发布时间】:2020-10-16 13:27:19
【问题描述】:

正如我们所知,private 成员在派生类中是不可访问的(不仅仅是私有的),而 publicprotected 在派生类中可以直接访问。

  • 如果一个类将另一个类声明为friend,那么后者就可以完全访问第一个类的成员。

这是一个我试图理解但徒劳无功的例子:

class A
{
    public:
       int pub;
    private:
       int priv;
    protected:
        int prot;
    friend class D;
};

class B : public A // public inheritance
{
    int b = 0;
};

class C : private A
{
    int c = 0;

};

class D
{
     public:
        void foo(B);
        void bar(C);
};

void D::foo(B b)
{
    b.pub = 0;
    b.prot = 0;
    b.priv = 0; // why this works? although A::priv is inaccessible in derived classes because it is private in base class?
   // b.b = 0; // error. ok because b is private
}

void D::bar(C c)
{
 //   c.pub = 0; // error ok
 //   c.prot = 0; // error ok
 //   c.priv = 0; // error ok
 //   c.c = 0; // error. ok because c is private
}
  • 问题:尽管我们知道private 在派生类中是不可访问的,为什么D::foo 可以通过来自publicly 的对象访问A 的私有成员,该对象继承自Base A?那么为什么b.priv = 0; 有效呢?我们知道friendship 既不传递也不继承?

【问题讨论】:

  • “我们知道友谊既不是传递的也不是继承的?” - 你的例子没有违反这一点。只有A 部分被访问。
  • @StoryTeller-UnslanderMonica:但是为什么 D 的成员函数中的 B 实例甚至可以访问 A 的私有成员,而 C 的实例不能?我想这与继承类型有关。你可以解释吗?谢谢!

标签: c++ inheritance friend access-specifier


【解决方案1】:

class Dclass A 的朋友,它可以完全访问其publicprotectedprivate 成员。 class Bpublicly 继承 class A,这意味着,class D 可以访问1)class B 的基类。因此,在class D 中允许使用class B 的对象访问class Apriv 成员。


仅当您认为在朋友类DD::bar(C) 函数中访问pubprotpriv 会给出错误,因为class A 是@987654340 @ly 由class C 继承。

class C的情况下,它privately继承class A。正如您所指出的,D::bar(C) 函数的声明 c.pubc.protc.priv 给出了错误。因为class C继承class Aprivately。

如果我取消注释并编译,我在D::bar(C) 函数中遇到的错误是:

p.cpp:44:5: error: cannot cast 'C' to its private base class 'A'
    c.pub = 0;
    ^
p.cpp:21:11: note: declared private here
class C : private A
          ^~~~~~~~~
p.cpp:44:7: error: 'pub' is a private member of 'A'
    c.pub = 0;
      ^
p.cpp:21:11: note: constrained by private inheritance here
class C : private A
          ^~~~~~~~~
p.cpp:8:12: note: member is declared here
       int pub;

protpriv 成员也有同样的错误。

这些错误是由于private 继承了class A 并且与朋友class D 无关。尝试在朋友class D之外以类似的方式访问它,你会得到同样的错误。

使用 C 风格转换你可以cast a derived class to private base class,像这样:

void D::bar(C c)
{
    ((A*)&c)->pub = 0;
    ((A*)&c)->prot = 0;
    ((A*)&c)->priv = 0;
    //c.c = 0; // error. ok because c is private
}

现在,您可以访问class Cprivate,继承基类(class A)其朋友类class D中的私有成员。 请注意,在 D::bar(C) 函数中使用 C 样式转换的 priv 成员访问是工作正常,只是因为 class Dclass A 的朋友。 如果您尝试访问privately 的私有成员,使用 C 样式转换继承派生类中的基类,则不允许:

class C : private A {
    int c = 0;
    public:
      void Cfoo();

};

void C::Cfoo() {
        ((A*)this)->pub = 100;
        ((A*)this)->priv = 100;   // error: 'priv' is a private member of 'A'
}

1)。 引用this答案:

让我们考虑一个类Base 和一个继承自Base 的类Child

  • 如果继承是public,所有知道BaseChild 也知道 Child 继承自 Base
  • 如果继承是protected,则只有Child 及其子级是 知道他们继承自Base
  • 如果继承是private,除了Child之外没有人知道 继承。

【讨论】:

    猜你喜欢
    • 2021-08-16
    • 1970-01-01
    • 1970-01-01
    • 2021-11-01
    • 2015-11-24
    • 1970-01-01
    • 2017-01-16
    • 2015-03-06
    • 1970-01-01
    相关资源
    最近更新 更多