【问题标题】:C++. Error: void is not a pointer-to-object typeC++。错误:void 不是指向对象的指针类型
【发布时间】: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++ 课程(这是我的猜测),那么你最终会达到这一点,所以暂时不用担心。

标签: c++ casting void-pointers abstract-data-type


【解决方案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* 指针。

        【讨论】:

          猜你喜欢
          • 2012-11-24
          • 2019-05-04
          • 2013-10-24
          • 2017-04-22
          • 1970-01-01
          • 2015-04-12
          • 2013-05-18
          • 2011-12-18
          • 2020-08-30
          相关资源
          最近更新 更多