указатель void на динамически выделяемый класс

Я пытаюсь передать void* функции, а затем внутри этой функции сделать так, чтобы указатель указывал на динамически созданный объект. Это то, что у меня есть до сих пор, но, похоже, это не работает:

основной:

int main()
{
  void* objPtr;

  setPtr(objPtr);
}

setPtr:

void setPtr(void*& objPtr)
{
  objPtr = new Obj1; 
  (*objPtr).member1 = 10; //error: expression must have pointer-to-class type
}

Объект1:

struct Obj1
{
  int member1;
};

заранее спасибо


person Logan Besecker    schedule 03.09.2012    source источник
comment
Вроде не работает не режется. Какое неожиданное поведение вы видите или какую ошибку компилятора вы получаете? Вам, вероятно, нужны скобки в new Obj1(), но я уверен, что есть и другие проблемы.   -  person David Grayson    schedule 03.09.2012
comment
когда я пытаюсь присвоить (общедоступной) переменной-члену значение, он говорит, что выражение должно иметь тип указателя на класс   -  person Logan Besecker    schedule 03.09.2012
comment
@LoganBesecker Эта проблема не связана с приведенным выше кодом. Вам нужно будет показать код, определяющий класс и его члены.   -  person jogojapan    schedule 03.09.2012
comment
Есть ли причина, по которой вы передаете указатель как void * вместо Obj1 *?   -  person jogojapan    schedule 03.09.2012
comment
@jogojapan У меня есть массив void*, поэтому я могу иметь разные индексы массива, указывающие на разные типы объектов   -  person Logan Besecker    schedule 03.09.2012
comment
Ok. Вы, конечно, можете это сделать. Но это подразумевает отказ от безопасности типов; Итак, в качестве последнего комментария: вы можете рассмотреть альтернативы, такие как иерархия классов полиморфа или использование boost::variant<>.   -  person jogojapan    schedule 03.09.2012


Ответы (2)


Что ж, конечно: void* не указывает на тип класса, поэтому его нельзя использовать для доступа к членам. C++ статически типизирован. Компилятор видит void* и все. Он не будет пытаться выяснить, на какой тип объекта на самом деле указывает указатель — вы должны указать это с помощью приведения:

objPtr->whatever; // fails: objPtr is not a pointer-to-class-type

((actual_type*)objPtr)->whatever; // okay: cast to actual_type*

Ну, это программист C во мне. Некоторые люди предпочитают использовать здесь static_cast:

static_cast<actual_type*>(objPtr)->whatever; // okay: cast to actual_type*

Однако, как бы вы это ни делали, вы должны быть уверены, что objPtr на самом деле указывает на объект типа actual_type.

person Pete Becker    schedule 03.09.2012
comment
Я не видел (objPtr*).member1 = 10; часть, когда я начал писать свой ответ - person Seçkin Savaşçı; 03.09.2012
comment
о, ранее я пытался (actual_type*)objPtr-›что угодно, но не имел круглых скобок вокруг всей внешней пары круглых скобок - person Logan Besecker; 03.09.2012
comment
@LoganBesecker - (actual_type*)objPtr->whatever говорит притвориться, что тип objPtr->whatever равен actual_type*. Легко сделать ошибку, когда вы впервые вникаете в эти вещи. - person Pete Becker; 03.09.2012
comment
Спасибо, Пит! Но у меня есть еще один вопрос, немного не по теме. Есть ли разница между способами приведения типов C и C++? Сначала меня учили стилю C, но теперь мне интересно, есть ли какие-то тонкие (или не очень) различия между тем, как они работают. - person Logan Besecker; 03.09.2012
comment
@Logan: приведения C ++ более строгие, чем приведения C. Вы не можете использовать static_cast для удаления квалификатора const (для этого вам нужно использовать const_cast), помимо других ограничений. Приведения в стиле C универсальны и могут выполнять все функции различных приведений C++. Также гораздо проще искать в базе кода экземпляры ключевых слов, таких как static_cast, чем (typename), хотя, честно говоря, я никогда не видел, чтобы кто-то действительно делал это. Одним из недостатков приведения типов C++ является то, что они требуют большего набора текста. - person Adam Rosenfield; 03.09.2012
comment
о, интересно; Я никогда не понимал, зачем людям печатать лишний раз, но теперь это имеет смысл - person Logan Besecker; 03.09.2012

EDIT: проблема владельца вопроса оказывается другой, этот ответ означает то же самое, что и реализованный с указателем на указатели. Обратитесь к реальному ответу Пита Беккера о правильном кастинге.

int main()
{
  void* objPtr;

  setPtr(&objPtr);
}

setPtr:

void setPtr(void** objPtr)
{
  *objPtr = new Obj1; //where Obj1 is user defined class type
}

То, что я делаю здесь, это просто передача указателя C-way, функция setPtr принимает указатель на указатель void и устанавливает указатель void, как предполагалось.

person Seçkin Savaşçı    schedule 03.09.2012
comment
Вы хотели объявить функцию как setPtr(void ** objPtr)? - person jogojapan; 03.09.2012
comment
Не компилируется: невозможно разыменовать void*. - person Pete Becker; 03.09.2012
comment
** разыменовывает указатель..? Что именно он делает? - person 0x499602D2; 03.09.2012
comment
@JohnSaunders - код теперь по существу такой же, как исходный код, за исключением того, что адрес, который нужно изменить, передается с указателем вместо ссылки. Это не влияет на реальную проблему. - person Pete Becker; 03.09.2012
comment
@PeteBecker: было бы неплохо иметь информацию в своем ответе. - person John Saunders; 03.09.2012
comment
@JohnSaunders - это не мой ответ. - person Pete Becker; 03.09.2012
comment
@PeteBecker: извините, было бы все же иметь больше информации в ответе - это то, о чем я просил. - person John Saunders; 03.09.2012
comment
@JohnSaunders Как я могу объяснить больше? - person Seçkin Savaşçı; 03.09.2012