Форум программистов, компьютерный форум CyberForum.ru

Передача объекта параметром и последующее изменение - C++

Восстановить пароль Регистрация
 
#pragma
Временно недоступен
 Аватар для #pragma
952 / 223 / 6
Регистрация: 12.04.2009
Сообщений: 921
26.01.2010, 16:08     Передача объекта параметром и последующее изменение #1
Неразбериха с классами.
Я создаю экземпляр класса,и далее указатель на него его передаю параметром самому себе.Так можно вообще делать? Заранее извиняюсь за бред,т.к. классы я учу "в процессе".
Выглядит всё это примерно так:
C++
1
2
3
4
5
expr_Node_t *operand1 = syntax_Primary(vars,arrays,labels);
//   ...
operand2 = syntax_Primary(vars,arrays,labels);
operand1->NewBinOp (operand1,operand2,OP_DIVIDE);
//   ...
В функции же происходит следующее:
C++
1
2
3
4
5
6
7
8
9
10
  expr_Node_t *Expression::NewBinOp (expr_Node_t *object,
                                     expr_Node_t *operand2, OpKind oper)
  {
     expr_Node_t *operand1 = new expr_Node_t (*object); // резервируем объект перед изменением
     kind                = EK_BINOP;
     data.binop.kind     = oper;
     data.binop.operand1 = operand1;
     data.binop.operand2 = operand2;
     return this;
  }
Зарезервировать объект,я думаю,необходимо перед изменением,так как все поля data внутри класса - unions (вроде бы анонимные,судя по сообщениям gcc),выглядят так:
union
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
        union
        {
           ...
           struct {                 // Unary operation
              OpKind kind;
              expr_Node_t *operand;
           } unop;
           struct {                 // Binary operation
              OpKind kind;
              expr_Node_t *operand1;
              expr_Node_t *operand2;
           } binop;
         ...
        } data;

Имеет ли это смысл вообще?
Будет ли это работать?
Нужно ли писать конструктор-копировщик в этом случае?
Целью этого всего является построение древовидной структуры из экземпляров класса,как вы догадались.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16825 / 5246 / 321
Регистрация: 30.03.2009
Сообщений: 14,127
Записей в блоге: 26
26.01.2010, 21:55     Передача объекта параметром и последующее изменение #2
C++
1
operand1->NewBinOp (operand1,operand2,OP_DIVIDE)
Насколько я понимаю, сия строка должна создавать новый экземпляр класса. А ты пытаешь существующий экземпляр затащить сам в себя. Если я правильно понимаю то, что ты хочешь, то это должно выглядеть как

C++
1
operand1 = new expr_Node_t (operand1,operand2,OP_DIVIDE); // <-- это конструктор для создания двухоперандного узла
а то, что у тебя сделано в качестве NewBinOp, должно быть конструктором.

Поскольку в твоём случае все expr'ы создаются динамически и вообще не должны копироваться друг в друга (имею в виду не должны копироваться экземпляры класса, указатели конечно же можно), то я бы вообще сделал copy-конструтор, в котором влепил бы вызов Fatal, т.к. таких действий быть не должно

Добавлено через 21 минуту
"это конструктор для создания двухоперандного узла" читать как "инициализации"

В твоём примере ты инициализируешь поля существующего экземпляра. А надо инциализировать поля вновь созданного экземпляра. Т.е. вместо "kind = EK_BINOP" должно быть "operand1->kind = EK_BINOP" и т.д. А вместо "return this" должно быть "return operand1". При таком подходе идеологически это перестаёт быть методом класса, а является обычной функцией

В Си++ есть возможность в одном операторе создать новый объект в динамической памяти и вызвать процедуру для инициализации полей (оператор new). В Си нет возможности, а потому там обычно создаётся функция, внутри которой делается выделение памяти и инициализация полей
#pragma
Временно недоступен
 Аватар для #pragma
952 / 223 / 6
Регистрация: 12.04.2009
Сообщений: 921
26.01.2010, 22:34  [ТС]     Передача объекта параметром и последующее изменение #3
Да,надо тут обмозговать.Просто когда всё перевёл на классы,оказалось,что нужно или менять структуру построения дерева,или идти на какие-то хитрости.Я недаром привел этот код:
C++
1
2
3
4
expr_Node_t *operand1 = syntax_Primary(vars,arrays,labels);
...
operand2 = syntax_Primary(vars,arrays,labels);
operand1->NewBinOp (operand1,operand2,OP_DIVIDE);
То есть operand1 уже инициализирован на время вызова NewBinOp,и в случае просто числа,а не двухаргументной операции его нужно возвратить из функции.Если же создавать ещё один операнд,который вместит два операнда и операцию,то тогда встаёт проблема,что и когда возвращать из функции.
А моя цель была просто выделить память под объект,инициализировать её,а потом уже менять исходный объект,делая его уже вместилищем для двух операндов,и тогда оба операнда "не потеряются"
***
Вообще у меня такой общий вопрос начинающего созрел для С++: вот есть в Си какие-то данные,содержащиеся в неком сегменте памяти,а в С++ есть экземпляры классов.Можно ли работать в С++ с экземпляром класса также как просто с неким отрезком памяти,также её копировать,то есть с точки зрения указателей ничего не меняется?
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16825 / 5246 / 321
Регистрация: 30.03.2009
Сообщений: 14,127
Записей в блоге: 26
26.01.2010, 22:59     Передача объекта параметром и последующее изменение #4
Для начала опишу более подробно, что я имел в виду в предыдущем посте:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class expr_Node_t
{
  // Конструктор для формирования двухаргументной операции
  expr_Node_t (const expr_Node_t *operand1, const expr_Node_t *operand2, OpKind oper);
  ...
};
...
 
expr_Node_t::expr_Node_t (const expr_Node_t *operand1, const expr_Node_t *operand2, OpKind oper)
{
     kind                = EK_BINOP;
     data.binop.kind     = oper;
     data.binop.operand1 = operand1;
     data.binop.operand2 = operand2;
}
 
...
expr_Node_t *operand1 = syntax_Primary(vars,arrays,labels);
//   ...
operand2 = syntax_Primary(vars,arrays,labels);
 
// Здесь мы создаём узел и сразу же к нему подвешиваем два уже существующих узла
// Указатель operand1 больше не нужен, ибо это только указатель. Технически этот момент
// исполняется аналогично коду
//
// expr_Node_t *tmp = malloc (...);
// tmp->constructor_expr_Node_t (operand1,operand2,OP_DIVIDE);
// operand1 = tmp
//
// Т.е. ничего у тебя не потеряется
operand1 = new expr_Node_t (operand1,operand2,OP_DIVIDE);
...
> То есть operand1 уже инициализирован на время вызова NewBinOp

operand1 - это УКАЗАТЕЛЬ. Это не объект. Он у тебя указывает на какой-то экземпляр класса, выделенный в памяти. Далее этот указатель ты передал в конструктор вновь созданного объекта. Внутри конструктора этот указатель у тебя запомнился. Теперь в operand1 мы записали указатель на вновь созданный объект. А operand1->data.binop.operand теперь смотрит туда, куда до вызова new смотрел operand1

> А моя цель была просто выделить память под объект,инициализировать её,а потом уже менять исходный объект

Не совсем понятно, зачем, но тогда это должно выглядеть так:

C++
1
2
3
tmp = new expr_Node_t;
tmp->NewBinOp (operand1,operand2,OP_DIVIDE);
operand1 = tmp;
При этом из NewBinOp выкидывается new, метод становится void и переименовывается во что-то типа InitBinOp, поскольку он уже только инициализирует, но новый экземпляр не создаёт. Всё это можно было бы написать в виде одной строки, как я указал выше

> Можно ли работать в С++ с экземпляром класса также как просто с неким отрезком памяти,также её копировать,то есть с точки зрения указателей ничего не меняется?

Можно. Но Си++ на то и разрабатывали, чтобы в программе вот таких вот ковыряний было как можно меньше. Либо приведи более конкретный пример, что ты имеешь в виду
Yandex
Объявления
26.01.2010, 22:59     Передача объекта параметром и последующее изменение
Ответ Создать тему
Опции темы

Текущее время: 20:09. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru