Java 在C+中调用私有成员函数+;
我来自Java,那里不允许减少派生类中的访问修饰符。对于Instance,以下内容不是用Java编译的:Java 在C+中调用私有成员函数+;,java,c++,inheritance,virtual-functions,Java,C++,Inheritance,Virtual Functions,我来自Java,那里不允许减少派生类中的访问修饰符。对于Instance,以下内容不是用Java编译的: public class A{ public void foo(){ } } public class B extends A{ @Override private void foo(){ } //compile-error } 但是,C++中很好: struct A { A(){ } virtual ~A(){ } A(A&&a
public class A{
public void foo(){ }
}
public class B extends A{
@Override
private void foo(){ } //compile-error
}
<>但是,C++中很好:
struct A {
A(){ }
virtual ~A(){ }
A(A&&){ }
public:
virtual void bar(){ std::cout << "A" << std::endl; }
};
struct B : public A{
private:
virtual void bar(){ std::cout << "B" << std::endl; }
};
int main()
{
A *a = new B;
a -> bar(); //prints B
}
结构A{
A(){}
虚拟~A(){}
A(A&&{}
公众:
虚拟空心条(){std::cout正如您所观察到的,访问说明符是基于指针的类型工作的,而不是基于动态类型。因此,在本例中,在B中指定private意味着无法通过指向B的指针访问函数。因此,在客户端不应使用point的情况下,这可能有助于保持锁定ers到B(或在堆栈上创建B)。基本上,在B的构造函数是私有的情况下,您通过返回
唯一\u ptr
的工厂创建B(可能还有A的其他子级)。在这种情况下,您可以将B的所有方法都指定为私有。原则上,这可以防止客户端“滥用”通过向下动态转换唯一的_ptr,然后直接访问B的接口,可以创建该接口
<>我并不认为这是应该做的;它是一种比C++更为流行的JavaY方法。一般来说,如果客户希望通过基类指针在堆栈上使用派生对象而不是堆上,则应该是能够的。它提供更好的性能,而且更易于推理。它在通用代码中也更好。
编辑:我想我应该澄清一下。考虑下面的代码:
enum class Impl {FIRST, SECOND, THIRD};
unique_ptr<A> create(Impl i) {
...
}
如果用户有这样的代码,并且您删除或重命名了类B,则他们的代码将中断。通过将B的所有方法设置为私有,您可以使B指针对用户无效,从而确保他们按照预期使用接口
正如我前面所说的,在C++中,我并不特别提倡用这种方式编程。但是,可能确实需要派生类是纯实现细节;在这种情况下,更改访问说明符可以帮助实现它。默认情况下,结构是公共的。就个人而言,我不建议更改访问级别,因为我认为这可能会令人困惑。但是,我不知道为什么它会被视为不安全,也不知道为什么它会有用。与此相关,由非虚拟公共函数调用私有虚拟函数可能会很有用。请参阅NVI(非虚拟接口)习惯用法。@JamesAdkison它是“不安全的”因为它允许外部代码直接调用私有函数,这与私有函数的整个观点相矛盾。@immibis我的意思是从UB的角度来看是不安全的。基类希望它是公共的,所以在我看来,派生类期望公共访问之外的任何东西都是错误的。另一个答案:
auto a = create(Impl::FIRST);
auto b = dynamic_cast<B *>(a.get());
// Use b below, potentially avoiding vtable