class base {
public:
virtual void doSomething() = 0;
};
class derived : public base {
private: // <-- Note this is private
virtual void doSomething()
{ cout << "Derived fn" << endl; }
};
现在,如果我执行以下操作:
base *b = new child;
b->doSomething(); // Calls the derived class function even though that is private
问题:
现在,如果我将继承访问说明符从public更改为protected / private,我会收到编译错误:
'type cast' : conversion from 'Derived *' to 'base *' exists, but is inaccessible
注意:我知道继承访问说明符的概念。所以在第二种情况下,因为它是派生私有/受保护的,所以它是不可访问的。但我想知道第一个问题的答案。任何意见都将受到高度赞赏。
答案 0 :(得分:6)
访问控制在编译时实现,而不是在运行时实现,而多态(包括使用虚函数)是运行时功能。
答案 1 :(得分:6)
在第一种情况下,访问检查在完成调用的静态类型上完成(因为它总是完成)。 *b
的静态类型为base
,在这种情况下,doSomething()
为public
。
C ++ 03 11.6“访问虚拟功能”说:
虚拟功能的访问规则(第11节)由确定 它的声明并且不受函数规则的影响 以后覆盖它。 [实施例:
class B { public: virtual int f(); }; class D : public B { private: int f(); }; void f() { D d; B* pb = &d; D* pd = &d; pb->f(); //OK:B::f()is public, // D::f() is invoked pd->f(); //error:D::f()is private }
-end example]
使用表达式的类型在调用点检查访问,该表达式用于表示调用成员函数的对象(上例中为B *)。成员函数在定义它的类中的访问(上例中的D)通常是未知的。
请特别注意“成员函数在其定义的类中的访问权限(上例中的D)通常是未知的”。通常,在您的示例中调用b->doSomething();
时,编译器可能根本不了解derived
(或child
),更不用说是否访问{ {1}}是私有的。
答案 2 :(得分:0)
私有函数意味着对外部世界和派生类隐藏。虽然您要覆盖父级DoSomething的访问说明符并将其设为私有,但您要实例化基类;所以在第一种情况下,你可以调用base的DoSomething,因为它是公开的。如果要阻止派生自派生类的人员,可以使用此方案。
在第二种情况下,private
访问说明符导致基类的成员不会向派生类的用户公开,这有效地使派生类无用。