简体   繁体   English

在自动范围内使用实例时需要“公共”访问修饰符

[英]Requiring “public” access modifier when using instance in auto scope

Suppose we have two classes, one derived from other and it contains only one virtual non-pure method like this: 假设我们有两个类,一个类是从另一个类派生的,并且只包含一个虚拟的非纯方法,如下所示:

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();
}

Why, if we do not specify explicitly "public" access modifier in Derived class (so, compiler assumes that it's private) it wouldn't compile? 为什么,如果我们在派生类中未明确指定“ public”访问修饰符(因此,编译器认为它是私有的),它将无法编译? Why instantiation way(via pointer and via regular variable) does affect to the visibility scope? 为什么实例化方式(通过指针和通过正则变量)会影响可见性范围? Is there any rationale regarding this behavior? 关于此行为是否有任何依据?

Many thanks! 非常感谢!

If you don't write public: then it's as if you've written private: . 如果您不写public: :,就好像您写了private: If you're asking why the language doesn't automatically switch to public: for Derived::method() (because it overrides Base::method() which is already public)… well, it could! 如果您要问为什么语言不自动切换为public:语言public:对于Derived::method() (因为它会覆盖已经是公共语言的Base::method() )……可以! This would be possible. 这是可能的。

However, it would also be extremely confusing and misleading when reading the code. 但是,在阅读代码时也将造成极大的混乱和误导。 As a programmer I much prefer that my class definition isn't fundamentally altered behind my back like that. 作为程序员,我非常希望我的类定义不会像这样从根本上改变。

The compiler throws out an error (as you've discovered) allowing me to make the change myself as I deem appropriate (whether that's making Derived::method() public, or Base::method() private!), which in my opinion is by far the best outcome. 编译器抛出一个错误(如您所发现的),允许我在我认为适当的情况下自己进行更改(无论是将Derived::method()公开还是Base::method()私有!),在我自己意见是迄今为止最好的结果。

If instead you're asking why a difference in visibility even matters at all, then that seems fairly obvious, does it not? 相反,如果您问的是为什么可见性差异甚至仍然很重要,那么这似乎很明显,不是吗? If the user were calling a function through the Base class interface, in which method() is public, and this ended up automatically invoking a private function in a derived class, that violates the contract of the derived class. 如果用户通过Base类接口调用一个函数,其中method()是公共的,则最终会自动调用派生类中的private函数,这违反了派生类的约定。 And because it's only the names that are protected by these visibility rules, the language adds an extra check for overridden methods to extend that protection as much as possible in the case of virtual function dispatch. 而且由于只有这些可见性规则保护了名称 ,因此该语言为覆盖的方法添加了额外的检查,以在虚拟函数分派的情况下尽可能地扩展该保护。

Something very similar is given as an example in the standard where the rules for these things are specified [class.access.virt]: 在标准中给出了一个非常相似的示例,其中为这些事物的规则指定了[class.access.virt]:

1 The access rules (Clause 11) for a virtual function are determined by its declaration and are not affected by the rules for a function that later overrides it. 1虚拟函数的访问规则(第11条)由其声明确定,并且不受后来覆盖该函数的函数规则的影响。

[ Example: [示例:

 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 ] —结束示例]

2 Access is checked at the call point using the type of the expression used to denote the object for which the member function is called (B* in the example above). 2在调用点使用用于表示为其调用成员函数的对象的表达式的类型(在上例中为B *)检查访问。 The access of the member function in the class in which it was defined (D in the example above) is in general not known. 通常不知道在定义成员函数的类中访问成员函数的情况(上述示例中的D)。

The above answer both your questions: 以上回答了您的两个问题:

  1. Why does it not compile - as per rule 2 above access is checked using the type of the expression (ie the static not dynamic type) 为什么不编译-根据上述规则2,使用表达式的类型(即静态而非动态类型)检查访问权限
  2. What is the rationale - again as described above it is generally not known what the dynamic type is. 基本原理是什么-再次如上所述,通常不知道动态类型是什么。 To demonstrate, consider this: You can link new derived classes to an existing code defining a base class without recompiling this code: then clearly it would have no chance of determining the access controls of the derived (which didn't even exist when it was compiled). 为了说明这一点,请考虑以下问题:您可以将新的派生类链接到定义基类的现有代码,而无需重新编译该代码:然后,很显然,它没有机会确定派生类的访问控制(当它被创建时甚至不存在)编译)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM