防止程序员使用任何技巧来访问私有类成员

Prevent programmer from using any trick to access private class member

本文关键字:访问 成员 程序员 任何技      更新时间:2023-10-16

通过声明成员private,非友元函数不能直接访问该成员。但是有一种方法可以通过使用指针的类型强制转换来访问它们,例如:

class Foo {
  private:
    int value;
  public:
    inline int get() {
      return value;
    }
    inline Foo (int value) {
      Foo::value = value;
    }
} foo(1234);
int main() {
  using namespace std;
  cout << foo.display() << endl; // display 1234
  int *p = (int *)(&foo); // HERE!
  *p = 5678;
  cout << foo.display() << endl; // display 5678, foo.value has been changed
  return 0;
}

我们能阻止用户使用这些技巧吗?或者我们可以禁止将Foo *转换为int *吗?

嗯,不,不可能阻止一个有决心的程序员进行显式类型转换,因为一个足够有决心的程序员可以使用的方法几乎是无限的——特别是如果愿意接受潜在的未定义行为的话。

从哲学上讲,c++类型系统通常被设计成使意外事件更难发生。然而,它不是为了防止程序员故意破坏类型系统而设计的。

通过使用多种技术组合可以使事情变得更加困难;

  1. 使用粉刺习语(parapura rajkumar在回答中已经提到)
  2. 向成员(包括pimpl)引入偏移量。例如,对于程序员来说,实现细节可能会偏移18个字节,这并不一定很明显。
  3. 为你的类提供一个私有的operator&(),这将防止使用&object来获取对象的地址。
  4. 不要提供返回this的成员函数,不要返回任何私有或受保护类数据的地址(或引用)。而且没有公开的数据。
然而,事情是,一个足够有决心的程序员会找到一种方法来解决像这样的各种技巧,即使没有访问源代码。这些类型的技巧也有不幸的影响,使开发人员难以以您可能希望的更常用的方式使用您的类。

一种选择是使用PIMPL习惯用法,并且不将实现类头文件作为库的一部分。

class A
{
    Aimpl* a_;
public:
    int getValue();
};

现在用户可以访问但是不知道如何修改Aimpl的内部结构

您无法阻止任何人编写您所展示的看似有效且可工作的代码。

似乎是因为

 *p = 5678;

实际上是未定义的行为,不能指望给出与您相同的结果。