【问题标题】:C++ protected member inheritanceC++ 受保护的成员继承
【发布时间】:2016-06-12 15:28:47
【问题描述】:

我的问题是为什么我不能通过指向基类的指针调用派生类中的受保护的虚拟成员函数,除非将派生类声明为基类的朋友?

例如:

#include <iostream>

class A {
  friend class C;  // (1)
protected:
  virtual void foo() const = 0;
};

class B : public A {
  void foo() const override { std::cout << "B::foo" << std::endl; }
};

class C : public A {
  friend void bar(const C &);
public:
  C(A *aa) : a(aa) { }
private:
  void foo() const override {
    a->foo();       // (2) Compile Error if we comment out (1)
    //this->foo();  // (3) Compile OK, but this is not virtual call, and will cause infinite recursion
    std::cout << "C::foo" << std::endl;
  }
  A *a;
};

void bar(const C &c) {
  c.foo();
}

int main() {
  B b;
  C c(&b);
  bar(c);

  return 0;
}

输出是

B::foo
C::foo

在上面的代码中,我想通过C类的成员a调用虚函数foo()(不是编译时通过this的静态绑定),但是如果我不做@ 987654327@作为A的好友,来电不合法。

我认为C是继承自A,所以它可以访问Aprotected成员,但是为什么实际上并没有发生呢?

【问题讨论】:

  • 嗯,从技术上讲,a-&gt;foo(); 也不是虚拟通话。要在基类中调用方法foo,请像这样调用它:A::foo ();
  • @AlgirdasPreidžius 通过指向基类的指针调用不是虚拟调用吗?另外A::foo是一个没有定义的纯虚函数,我认为a.A::foo这样的调用是在编译时绑定的,在这种情况下会报错。
  • @AlgirdasPreidžius 不,正如 OP 所示,a-&gt;foo() 的结果是 B::foo

标签: c++ access-control


【解决方案1】:

C 可以访问它自己的基类的受保护成员,但不能访问任何其他A 的成员。

在您的示例中,参数a 是完全不相关的类B 的一部分,C 对其没有访问权限(除非您将其设为朋友)。

【讨论】:

  • 感谢您的回答。但是我还有一个问题:按照标准,虚函数的访问级别是由它在基类中的声明决定的。所以编译器在编译时不会知道参数aB 类对象的一部分。我应该如何理解这个问题?
  • a 参数是否恰好是其他 C 对象的一部分实际上并不重要。编译器无法判断它是否只是获得指向A 的指针。它必须有一个已知的C 对象才能访问其基类。
猜你喜欢
  • 2014-06-09
  • 2023-03-03
  • 2016-09-24
  • 2018-12-27
  • 2012-10-03
  • 2014-01-30
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
相关资源
最近更新 更多