C++。错误:void 不是指向对象的指针类型

Posted

技术标签:

【中文标题】C++。错误:void 不是指向对象的指针类型【英文标题】:C++. Error: void is not a pointer-to-object type 【发布时间】:2011-12-18 11:36:29 【问题描述】:

我有一个 C++ 程序:

struct arguments

  int a, b, c;  
  arguments(): a(3), b(6), c(9) 
;

class test_class
  public:

    void *member_func(void *args)
      arguments vars = (arguments *) (*args); //error: void is not a 
                                              //pointer-to-object type

      std::cout << "\n" << vars.a << "\t" << vars.b << "\t" << vars.c << "\n";
    
;

编译时会报错:

error: ‘void*’ is not a pointer-to-object type

有人可以解释我做错了什么来产生这个错误吗?

【问题讨论】:

是的,有。您是否尝试过给args 提供另一种数据类型? 在这个例子中你没有任何“抽象类型”(我假设你的意思是抽象基类)。您可能指的是*(arguments *)args,它将argsvoid * 转换为arguments *然后 取消引用它。您当前的代码尝试取消引用 void *(这是非法的),然后将取消引用的值转换为 arguments *,这几乎肯定不是您想要的。 @Chris 是的,这就是我想要做的,感谢您的澄清。顺便说一句,我认为结构和类被认为是抽象类型,而例如。 int、float 是非抽象的。 另外,您的 member_func 返回 void * 但您在任何地方都没有 return 语句。另外,为什么需要使用void *?为什么不能只使用arguments *(或者,更好的是,只使用argumentsconst arguments&amp;)? @MattMunson - 不,“抽象”是指具有纯虚拟成员函数的类(或结构)。我不知道你对 C++ 了解多少,但如果你正在学习 C++ 课程(这是我的猜测),那么你最终会达到这一点,所以暂时不用担心。 【参考方案1】:

在将 void * 转换为具体类型之前,您正在取消对它的引用。你需要反过来做:

arguments vars = *(arguments *) (args);

这个顺序很重要,因为编译器不知道如何将* 应用到args(这是一个void *,不能取消引用)。你的 (arguments *) 告诉它该做什么,但为时已晚,因为取消引用已经发生。

【讨论】:

但请在此处使用static_cast -- 这样您会收到更好的错误消息... @Billy static_cast 做什么? @Matt: 和 C 风格的演员一样,除了更有限。 static_cast 不允许删除 const、重新解释指针类型以及其他一些讨厌的事情。一般来说,static_casts 的任何东西都可以跨平台/架构工作。更多详细信息请参见 C++ 标准的第 5.2.9 节(假设为 C++03)【参考方案2】:

重现上述错误的简单例子:

#include <iostream>
using namespace std;
int main() 
  int myint = 9;             //good
  void *pointer_to_void;     //good
  pointer_to_void = &myint;  //good

  cout << *pointer_to_void;  //error: 'void*' is not a pointer-to-object type

上面的代码是错误的,因为它试图取消引用指向 void 的指针。这是不允许的。

现在运行下面的下一个代码,如果你理解为什么下面的代码运行而上面的代码没有运行,你将更好地理解幕后发生的事情。

#include <iostream>
using namespace std;
int main() 
    int myint = 9;
    void *pointer_to_void;
    int *pointer_to_int; 
    pointer_to_void = &myint;
    pointer_to_int = (int *) pointer_to_void;

    cout << *pointer_to_int;   //prints '9'
    return 0;

【讨论】:

【参考方案3】:

您将* 放在错误的位置。所以你正在尝试取消引用void*。 试试这个:

arguments vars = *(arguments *) (args);
std::cout << "\n" << vars.a << "\t" << vars.b << "\t" << vars.c << "\n";

或者,您可以这样做:(这也避免了复制构造函数 - 如 cmets 中所述)

arguments *vars = (arguments *) (args);
std::cout << "\n" << vars->a << "\t" << vars->b << "\t" << vars->c << "\n";

【讨论】:

保留它作为指针可能更好,因为它避免了复制构造函数。但是,OP 应该使指针(arguments *void *const【参考方案4】:

bdonlan 所说的问题是“在转换之前取消引用 void*”。

我认为这个例子会有所帮助:

#include <iostream>

using namespace std;

int main()




   void *sad;
   int s = 23;
   float d = 5.8;

   sad = &s;
   cout << *(int*) sad;//outputs 23//wrong: cout << *sad ;//wrong: cout << (int*) *sad;



   sad = &d;
   cout << *(float *) sad;//outputs 5.8//wrong: cout << *sad ;//wrong: cout << (float*) *sad;

   return 0;

【讨论】:

【参考方案5】:

*args 表示“对象(值)args 指向”。因此,它不能被转换为指向对象(参数)的指针。这就是它给出错误的原因

【讨论】:

【参考方案6】:

上面的问题是你试图尊重一个在 C 或 C++ 中不允许的 void 指针。

但是,这仍然有效:

#include <iostream>
using namespace std;
int main()

    int b=10;
    void *a=&b;
    int *ptr=(int*)a;
    cout<<*ptr;;
 

在将 void 指针转换为 int* 指针后,我们可以尊重 int* 指针。

【讨论】:

以上是关于C++。错误:void 不是指向对象的指针类型的主要内容,如果未能解决你的问题,请参考以下文章

指向对象开头的指针 (C++)

void*指针

从 2D 向量创建 1D 向量的函数(错误:表达式必须具有指向对象的指针类型)

[转载]C++中引用与指针的区别(详细介绍)

C语言 NULL赋结构体指针变量

当指向删除和指向不同的对象时,C++ 中的 Seg 错误指针