假设我们有两个类,一个派生自另一个类,它只包含一个虚拟的非纯方法,如下所示:
class Base
{
public:
virtual void method()
{
cout << "method() called from Base" << endl;
}
};
class Derived : public Base
{
public:
void method()
{
cout << "method() called from Derived" << endl;
}
};
int main()
{
Base *instance1 = new Derived();
instance1->method();
Derived derived;
derived.method();
}
为什么,如果我们没有明确指定&#34; public&#34; Derived类中的访问修饰符(因此,编译器假定它是私有的)它不会编译?为什么实例化方式(通过指针和通过常规变量)确实会影响可见性范围?关于这种行为有什么理由吗?
非常感谢!
答案 0 :(得分:1)
如果您不写public:
,那么就好像您已经写过private:
一样。如果你问为什么语言没有自动切换到public:
Derived::method()
(因为它会覆盖已经公开的Base::method()
)......好吧,它可以!这是可能的。
然而,在阅读代码时,它也会非常混乱和误导。作为一名程序员,我更喜欢我的课程定义并没有像我那样从根本上改变。
编译器抛出一个错误(正如您已经发现的那样),允许我在我认为合适的情况下自行进行更改(无论是Derived::method()
公开还是Base::method()
私人!),在我看来是迄今为止最好的结果。
相反,如果您不知道为什么可见度的差异甚至根本不重要,那么这似乎相当明显,不是吗?如果用户通过Base
类接口调用函数,其中method()
是公共的,并且最终自动调用派生类中的private
函数,则违反了派生类。并且因为它只是受这些可见性规则保护的名称,所以该语言为重写方法添加了额外的检查,以便在虚函数调度的情况下尽可能地扩展该保护。
答案 1 :(得分:1)
在标准中给出了非常类似的东西,其中指定了这些东西的规则[class.access.virt]:
1确定虚拟功能的访问规则(第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 }
- 结束示例]
2访问是 使用所用表达式的类型在调用点进行检查 表示调用成员函数的对象(B *中的 上面的例子)。成员函数在类中的访问权限 它的定义(上例中的D)通常是未知的。
以上回答了你的问题: