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

时间:2013-11-24 22:27:15

标签: java c++ private dynamic-binding

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 ++中这种行为背后的逻辑是什么?

2 个答案:

答案 0 :(得分:3)

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

以下情况说明了它的逻辑:想象一下,如果B没有公开地继承A,而是私下 - 这在C ++中是允许的,并且在继承本身是一个实现时使用详细信息,例如继承自stack的{​​{1}}类,但不希望公开矢量接口。在这种情况下,vector无法访问,但B::method工作正常,即使对象是A::method实例。

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

答案 1 :(得分:2)

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

以下是锁定和后置条件验证的示例:

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中,这可以通过受保护的方法实现,但这会将实现细节泄露给派生类的派生类,这可能是不受欢迎的。

至于私有化,否则公众成员参与其中,如果某人突然在function_impl中公开base,则不会破坏派生类。我不是说这样做是个好主意,但C ++通常只是假设你知道自己在做什么,因此它是一种如此灵活的语言。