【问题标题】:Handle , Void Pointer , Objects in C++C++ 中的句柄、空指针、对象
【发布时间】:2017-08-06 16:19:57
【问题描述】:

所以我在阅读Handle in C 上的文章并意识到我们将句柄实现为 void 指针,因此我们获得的“任何”对象/数据类型都可以将 void 指针转换为那种对象/数据并获取它的值。所以我基本上有两个担忧:

1.如果让我们说下面的例子取自Handle in C

 typedef void* HANDLE;   
 int doSomething(HANDLE s, int a, int b) {
         Something* something = reinterpret_cast<Something*>(s);
         return something->doit(a, b);
     }
       

如果我们将值传递给函数dosomething(21,2,2),这是否意味着HANDLE指向的值是21,如果是的话,当我们键入任何对象时如何将其转换为该对象,它是否能够使用它,例如在这个例子中,换句话说,指向对象Something的指针something将存储值21。

2.Secondly 链接还说“所以在你的代码中你只是传递 HANDLE 作为一个不透明的值”它实际上是什么意思?为什么我们要“传递句柄”?如果有人可以给出更令人信服的使用对象的句柄示例,那就太好了!

【问题讨论】:

  • 这是否意味着 HANDLE 指向的值是 21 不,这意味着 s 是 21。我怀疑那个内存地址有什么有趣的东西。
  • 我可能错了,但在代码中,您将 s 转换为另一种类型。实际地址永远不会改变

标签: c++ handle void-pointers


【解决方案1】:

1.:句柄是对象的标识符。由于“21”不是对象,而只是一个数字,因此您的函数调用无效。只有当's'确实指向Something 类型的结构时,您的代码才会起作用。简而言之,句柄只不过是指针,只不过是内存地址,因此“21”将被解释为内存地址,如果您尝试写入它会导致程序崩溃

2.:“不透明值”意味着使用您的代码的任何开发人员都不能对句柄标识的对象的内部结构进行任何假设。与指向结构的指针相比,这是一个优势,开发人员可以查看结构并做出一些假设,这些假设在您更改代码后将不再成立。 “传递”只是意味着:分配它并将其用作函数调用参数,如:

HANDLE s = CreateAnObject();
DoSomethingWithObject( s );
HANDLE t = s;

等等

顺便说一句:在实际代码中,您应该为对象的句柄赋予不同的名称,例如 EMPLOYEE_HANDLE、ORDER_HANDLE 等。 句柄的典型示例是 Windows 中的窗口句柄。它们识别窗口,但不会向您提供有关如何构建操作系统中的“窗口”内存结构的任何信息,因此 Microsoft 能够更改此内部结构,而不会有因更改“窗口”结构而破坏其他开发人员代码的风险。

【讨论】:

    【解决方案2】:

    如果我们将值传递给函数dsomething(21,2,2),那是否意味着HANDLE指向的值是21,

    没有。这只是意味着void* 的值是21。如果将21 视为指向Something 类型对象的指针的值,它很可能会导致未定义的行为。

    2.Secondly 链接还说“所以在你的代码中你只是传递 HANDLE 作为一个不透明的值”它实际上是什么意思?为什么我们要“传递句柄”?如果有人可以给出更令人信服的使用对象的句柄示例,那就太好了!

    手柄是不透明的,因为您无法通过它看到任何东西。如果句柄由void* 表示,则您将看不到有关该对象的任何信息,因为无法取消引用void*。如果句柄由 int 表示(作为代码中其他地方定义的某个数组的索引),则您无法查看句柄的值并理解相应对象所代表的含义。

    理解句柄的唯一方法是使用适合句柄类型的方法将其转换为指针或引用。

    在句柄由void* 表示的情况下,您发布的代码说明了如何提取指向具体对象的指针并理解该对象。

    如果句柄由int 表示,您可能会看到以下内容:

    int doSomething(HANDLE s, int a, int b) {
    
       // If the value of s is 3, something will be a reference
       // to the fourth object in the array arrayOfSomethingObjects.
    
       Something& something = arrayOfSomethingObjects[s];
       return something.doit(a, b);
    }
    

    【讨论】:

    • 这很有意义,但请您详细说明Something& something = arrayOfSomethingObjects[s];方法?是不是表示在一个对象类型的数组中如果s为3,那么看它在3处指的是哪个对象,然后把Something的类型赋值给something?
    • @GENIVI-LEARNER,我稍微更新了答案。当您使用 Something&amp; 时,您创建的是引用,而不是副本。
    【解决方案3】:

    我没有意识到有一篇关于 HANDLE 的事实上的文章或一种事实上的实现方式。它们通常是一个窗口结构,可以以任何 1985 年开发人员决定实现它们的方式实现。

    它真的和“东西”一样多的意思,或者更确切地说是“可以用来获取资源的东西”

    不要养成创建自己的“句柄”的习惯,当然也不要试图模仿 1985 年以来的代码习惯用法。空指针、reinterpret_casts 和 HANDLE 都是您应该不惜一切代价避免的事情。

    您唯一需要处理“HANDLE”的情况是在使用 Windows API 时,在这种情况下,文档会告诉您如何处理它。

    在现代 C++ 中,如果您想传递对象,请使用引用、指针和智能指针(包括 unique_ptr、shared_ptr、weak_ptr)并研究哪些场景需要哪些。

    【讨论】:

    • thingy 这个词解释了很多,因为 Handle 这个词有点令人困惑!谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多