【问题标题】:Void Pointers : how to use as a general class pointer?Void Pointers:如何用作通用类指针?
【发布时间】:2014-03-12 12:12:56
【问题描述】:

我有两个 cpp 类,比如说 ClassA 和 ClassB。我有两个相应地指向该类的指针,比如说pointerA 和pointerB。现在我有一个通用的 void* 指针,我想根据某些条件指向 ClassA 或 ClassB。在这种情况下会出现错误错误 C2227:'->GetPosition' 的左侧必须指向类/结构/联合/泛型类型类型是 'void *'。

如何避免此类错误?

ClassA { 
   void GetPosition();
}

ClassB { 
   void GetPosition();
}

main() {

   ClassA  *pointerA;
   ClassB  *pointerB;
   void    *generic_pointerAorB;

   pointerA = GetAddrOfClassA();
   pointerB = GetAddrOfClassB()

   generic_pointer = pointerA;

   //********************** error at the code below ******************************
   //error C2227: left of '->GetPosition' must point to class/struct/union/generic type. 
   //type is 'void *'

   generic_pointer->GetPosition(); 

   //*****************************************************************************



}

【问题讨论】:

标签: c++ pointers void-pointers


【解决方案1】:

void 指针没有称为GetPosition 的方法,并且指针本身不可能知道它指向您的某个类,因为它存储的是内存地址,而不是类型。您需要使用演员表:

reinterpret_cast<ClassA*>(generic_pointerAorB)->GetPosition();

但老实说,你应该做点别的事情——从某个具有virtual GetPosition() 方法的基类派生类,然后声明一个指向基类的指针。

class Base{
   virtual void GetPosition();

ClassA: public Base { 
   void GetPosition();
}

ClassB: public Base { 
   void GetPosition();
}

main(){
   Base* basePointer;
   // <-- other code here
   basePointer = pointerA;
   basePointer->GetPosition();

【讨论】:

  • 第一个带有 reinterpret_cast 的解决方案不是一个公认的解决方案,因为我不想一直指定要使用什么类。我在代码中所做的是: generic_pointerAorB = dynamic_cast(pointerA);我想对编译器说 generic_pointerAorB 现在指向 ClassA。什么是正确的解决方案?现在关于基类的虚函数,我在你推荐之前就想到了,但我认为它有点矫枉过正,除此之外,ClassA 和 ClassB 之间没有任何共同之处。一点都不喜欢:-(
  • 两个类都定义了一个同名的方法——连接它们的方法。在这种特殊情况下,这完全不是矫枉过正。此外 - 如果没有基类,真的没有办法做到这一点。您可以将基类视为与 Java 接口相同的方式。另请记住,C++ 允许您使用多重继承,因此您可以根据需要从多个基类派生类。
  • 我决定创建一个基类。谢谢。
【解决方案2】:

您不能取消引用 void * 类型。

原因很简单,编译器无法通过void * 类型知道generic_pointer(在您的情况下)实际指向了多少内存。

这样使用:

((ClassA*)generic_pointer)-&gt;GetPosition();

或等价的,

((ClassB*)generic_pointer)-&gt;GetPosition();

【讨论】:

  • 我意识到这在技术上是可行的,但我不鼓励这种代码。此外,编译器需要知道的不仅仅是对象的大小。它还需要在内存中进行布局。
  • 编译器不需要知道类的内存,因为类已经创建好了。它应该只指向那个类,正如我已经说过的那样,它是在我的代码中某处的堆中创建的。我想对编译器说,只要指向内存中的那个地址。请记住,所有指针的大小都是恒定的,并且根据操作系统具有 32 位或 64 位数据大小。
【解决方案3】:

如果您使用 C++,更好的方法是定义一个虚拟基类

class Base
{
public:
   virtual void GetPosition();
};

然后从 Base 派生 ClassA 和 ClassB

class ClassA: public Base
{
   void GetPosition();
}

class ClassB: public Base
{
   void GetPosition();
}

然后在你的程序中,不要声明 void*,而是使用 Base*;

Base* generic_pointer;

然后不是强制转换,

generic_pointer->GetPosition();

【讨论】:

  • 检查我写给@Paweł Stawarz的推荐
猜你喜欢
  • 2019-11-17
  • 1970-01-01
  • 2014-05-30
  • 2013-06-28
  • 1970-01-01
  • 1970-01-01
  • 2016-10-16
  • 2012-02-20
  • 1970-01-01
相关资源
最近更新 更多