繁体   English   中英

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

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

这在Java中是不允许的:

class A { 
    public void method() {}
}

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

它会生成编译错误:

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

但是,这在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
}

C ++中这种行为背后的逻辑是什么?

请记住, method的可见性仅在编译时解决,C ++没有运行时验证程序的概念。 编译器看到的是一个虚拟的A::method ,它不是私有的。 具体实现声明为私有,但只有在以编译器可见的方式直接调用此实现时才会相关,即如果您尝试通过B调用它直接访问它。

下面的例子说明了它的逻辑:想象一下,如果B不是公开地继承A ,而是私有 - 这在C ++中是允许的,并且在继承本身是一个实现细节时使用,例如从继承vectorstack类,但不想暴露矢量界面。 在这种情况下,它将是B::method无法访问的功能,但A::method工作正常,即使该对象是B实例。

正如Kerrek SB所说,Java在这里保护您免受一类错误的侵害,代价是删除合法选项。

对于虚拟私有方法部分,这允许实现NVI模式 ,以便您可以在使用继承的情况下执行不变检查或设置/拆除。

这是一个带锁和后置条件验证的示例:

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!
    }
};

在Java中,这可以通过受保护的方法来实现,但是这会将实现细节泄露给派生类的派生类,这可能是不希望的。

至于私有化,否则公共成员部分,如果有人突然在base使function_impl公开,它将不会破坏派生类。 我并不是说这是一个非常好的主意,但是C ++通常只是假设你知道你在做什么,因此它是如此灵活的语言。

暂无
暂无

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

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