[英]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 ++中是允许的,并且在继承本身是一个实现细节时使用,例如从继承vector
的stack
类,但不想暴露矢量界面。 在这种情况下,它将是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.