С++. Ошибка: void не является типом указателя на объект

У меня есть программа на С++:

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

Может кто-нибудь объяснить, что я делаю неправильно, чтобы произвести эту ошибку?

Ответы

Ответ 1

Вы разыгрываете void * перед тем, как придать его конкретному типу. Вам нужно сделать это наоборот:

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

Этот порядок важен, поскольку компилятор не знает, как применить * к args (который является void * и не может быть разыменован). Ваш (arguments *) сообщает, что делать, но это слишком поздно, потому что разыменование уже произошло.

Ответ 2

Пример Bare bones для воспроизведения описанной выше ошибки:

#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
}

Вышеприведенный код неверен, потому что он пытается разыменовать указатель на пустоту. Это не разрешено.

Теперь запустите следующий код ниже. Если вы понимаете, почему следующий код работает, а приведенный выше код не работает, вы будете лучше подготовлены, чтобы понять, что происходит под капотом.

#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";

В качестве альтернативы вы можете сделать это: (который также избегает конструктора копирования - как указано в комментариях)

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

Ответ 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

Проблема, описанная выше, заключается в том, что вы пытаетесь задержать указатель void, который не разрешен в C или C++.

Тем не менее, это все еще работает:

#include <iostream>
using namespace std;
int main()
{
    int b=10;
    void *a=&b;
    int *ptr=(int*)a;
    cout<<*ptr;;
} 

Мы можем ссылаться на указатели int * после приведения пустых указателей к указателям int *.