调用C++中的私有成员函数
Calling private member function in C++
我来自Java,在那里不允许减少派生类中的访问修饰符。对于instnace,以下内容不是用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&&){ }
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
}
演示
它在哪里有用?此外,这样做安全吗?
正如您所观察到的,访问说明符的工作原理是基于指针的类型,而不是基于动态类型。因此,在这种情况下,在B中指定private只意味着不能通过指向B的指针来访问函数。因此,在客户端不应该使用指向B(或在堆栈上创建B)的指针的情况下,这可能有助于锁定事物。基本上,在B的构造函数是私有的,并且您通过返回unique_ptr<A>
的工厂创建B(可能还有A的其他子级)的情况下。在这种情况下,您可以将B的所有方法指定为私有方法。原则上,这可以防止客户端通过向下动态投射unique_ptr,然后直接访问B的接口来"滥用"接口。
不过,我真的不认为应该这样做;它是一种比C++更Java-y的方法。通常,如果客户端希望在堆栈上使用派生对象,而不是通过基类指针在堆上使用,那么他们应该能够。它提供了更好的性能,而且更容易推理。它在泛型代码中也能更好地工作。
编辑:我想我应该澄清一下。考虑以下代码:
enum class Impl {FIRST, SECOND, THIRD};
unique_ptr<A> create(Impl i) {
...
}
假设这是创建使用A接口的具体实例的唯一方法。我可能希望派生类是纯粹的实现细节。例如,我可以在不同的类中实现这三个实现中的每一个,然后决定将三个实现的两个集中到一个具有不同选项的类中,等等。这与用户无关;他们的世界只是A的接口加上CCD_ 2函数。但现在假设一个用户碰巧查看了源代码,并知道FIRST
实现是使用B实现的。他们想要更好的性能,所以他们这样做:
auto a = create(Impl::FIRST);
auto b = dynamic_cast<B *>(a.get());
// Use b below, potentially avoiding vtable
如果用户有这样的代码,而您删除或重命名了类B,那么他们的代码就会中断。通过使B的所有方法都是私有的,可以使B指针对用户毫无用处,从而确保用户按预期使用接口。
正如我之前所说,我并不特别提倡用C++进行这种编程。但在某些情况下,您确实需要将派生类作为纯粹的实现细节;在这种情况下,更改访问说明符可以帮助强制执行它。
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 将公共但非静态的成员函数与ALGLIB集成
- 使用指向成员的指针将成员函数作为参数传递
- 将重载的成员函数传递给函数模板
- 我不小心调用了一个没有自己类对象的成员函数.但这是怎么回事呢
- 如何在C++中使用非静态成员函数作为回调函数
- C++错误C2600:无法定义编译器生成的特殊成员函数(必须首先在类中声明)
- 关联容器的下界复杂性:成员函数与非成员函数
- 在 C++ 中用派生类型重写成员函数
- 链表的泛型函数remove()与成员函数remove)
- 如何将lambda作为模板类的成员函数参数
- constexpr构造函数需要常量成员函数时出现问题
- 将自由函数绑定为类成员函数
- 区分非成员函数和头文件中的成员函数
- 如何从子成员函数修改父公共成员变量
- 保留对其他类的成员函数的引用
- 在运算符重载定义中使用成员函数(const错误)
- 内联如何影响模块接口中的成员函数
- 将成员函数指针作为参数传递给模板方法