简体   繁体   English

私有方法的动态绑定:Java与C ++

[英]Dynamic binding of private methods: Java vs. C++

This is not allowed in Java: 这在Java中是不允许的:

class A { 
    public void method() {}
}

class B extends A { 
    private void method() {}
}

It generates a compile error: 它会生成编译错误:

error: method() in B cannot override method() in A 
attempting to assign weaker access privileges; was public

However, this IS allowed in C++: 但是,这在C ++中是允许的:

class A { 
    public:
        virtual void method() {}
};

class B : public A { 
    private:
        void method() {}
};

int main(void) {
    A* obj = new B();
    obj->method(); // B::method is invoked, despite it being private
}

What's the logic behind this behavior in C++? C ++中这种行为背后的逻辑是什么?

Remember that the visibility of method is resolved purely at compile-time, C++ has no concept of a runtime verifier. 请记住, method的可见性仅在编译时解决,C ++没有运行时验证程序的概念。 What the compiler sees is a virtual A::method , which is not private. 编译器看到的是一个虚拟的A::method ,它不是私有的。 The concrete implementation is declared private, but that is only relevant when this implementation is directly invoked in a manner visible to the compiler, ie if you try to access it directly by calling it through B . 具体实现声明为私有,但只有在以编译器可见的方式直接调用此实现时才会相关,即如果您尝试通过B调用它直接访问它。

The logic of it is illustrated by the following case: Imagine if B didn't inherit from A publically, but privately — this is allowed in C++, and used when inheritance itself is an implementation detail, such as for a stack class inheriting from vector , but not wanting to expose the vector interface. 下面的例子说明了它的逻辑:想象一下,如果B不是公开地继承A ,而是私有 - 这在C ++中是允许的,并且在继承本身是一个实现细节时使用,例如从继承vectorstack类,但不想暴露矢量界面。 In that case it would be a feature for B::method to be inaccessible, but A::method working just fine, even if the object is a B instance. 在这种情况下,它将是B::method无法访问的功能,但A::method工作正常,即使该对象是B实例。

As Kerrek SB said, here Java is protecting you from one class of mistakes, at the cost of removing legitimate options. 正如Kerrek SB所说,Java在这里保护您免受一类错误的侵害,代价是删除合法选项。

As for the virtual private methods part, this allows one to implement the NVI pattern , so that you can do invariant checks or set-up/tear-down in a situation where inheritance is used. 对于虚拟私有方法部分,这允许实现NVI模式 ,以便您可以在使用继承的情况下执行不变检查或设置/拆除。

Here is an example with a lock and a postcondition verification: 这是一个带锁和后置条件验证的示例:

class base {
public:
    virtual ~base() = default;

    // Calls the derived class' implementation in a thread-safe manner.
    // @return A value greater than 42.
    int function() {
        std::lock_guard<std::mutex> guard(mutex);
        auto result = function_impl();
        assert(result > 42);
        return result;
    }

private:
    std::mutex mutex;
    virtual int function_impl() = 0; 
};

class derived : public base {
private:
    virtual int function_impl() override {
        return 0; // Whoops! A bug!
    }
};

In Java this could be achieved with protected methods, but that would leak implementation details to derived classes of derived classes which might be undesired. 在Java中,这可以通过受保护的方法来实现,但是这会将实现细节泄露给派生类的派生类,这可能是不希望的。

As for the privatising otherwise public members part, if somebody would suddenly make function_impl public in base , it won't break the derived classes. 至于私有化,否则公共成员部分,如果有人突然在base使function_impl公开,它将不会破坏派生类。 I'm not saying it's a very good idea to do this, but C++ usually just assumes you know what you're doing, hence it's such a flexible language. 我并不是说这是一个非常好的主意,但是C ++通常只是假设你知道你在做什么,因此它是如此灵活的语言。

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

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