【发布时间】: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,所以它可以访问A的protected成员,但是为什么实际上并没有发生呢?
【问题讨论】:
-
嗯,从技术上讲,
a->foo();也不是虚拟通话。要在基类中调用方法foo,请像这样调用它:A::foo ();。 -
@AlgirdasPreidžius 通过指向基类的指针调用不是虚拟调用吗?另外
A::foo是一个没有定义的纯虚函数,我认为a.A::foo这样的调用是在编译时绑定的,在这种情况下会报错。 -
@AlgirdasPreidžius 不,正如 OP 所示,
a->foo()的结果是B::foo。
标签: c++ access-control