2012-02-02 2 views
0

Основная проблема заключается в создании динамического класса. Что я сделал:Классы и указатели, как они работают?

ptr = new animal[2]; 

Я пытаюсь создать динамический массив размера 2, на который указывает указатель ptr. Проблема возникает, когда я пытаюсь эти операции:

ptr[0].setspeed(9); 
ptr++->setspeed(13); 

Я использую DDD (GDB) графический отладчик и когда я показываю PTR, я вижу только это указывает на один объект. Когда я пытаюсь установить скорость, первый, похоже, работает, но второй не будет (скорость по умолчанию равна 0). Печать только получает мусор.

Я не уверен, что происходит, пожалуйста, помогите.

Кроме того, когда я делаю:

ptr->print(); 

должен ли он печатать как для ptr[0] и ptr[1], или просто ptr[0]?

Кроме того, может кто-нибудь быстро нарисовать картину того, как выглядят ptr и новый динамический класс? То, как я это вижу, это ptr, указывающий на массив, размер массива два, каждый из которых имеет объект для животных.

#include <iostream> 
using namespace std; 

class animal 
{ 
    private: 
     int speed; 
     double position_x; 
     double position_y; 

    public: 
     animal() : speed(0), position_x(0), position_y(0) 
     { 
     } 

     animal (int v, double x, double y) 
     { 
      this->speed = v; 
      this->position_x = x;  
      this->position_y = y; 
     } 

     animal(const animal & g) 
     { 
      this->speed = g.speed; 
      this->position_x = g.position_x; 
      this->position_y = g.position_y; 
     } 

     ~animal(); 

     void print(); 

     int getspeed() { return this->speed; } 

     int getx() { return this->position_x; } 

     int gety() { return this->position_y; } 

     void setspeed(int s) { this->speed = s; } 
    }; 

    void animal::print() 
    { 
     cout << "speed: " << this->getspeed() << endl; 
     cout << "position_x: " << this->getx() << endl; 
     cout << "position_y: " << this->gety() << endl; 
    } 

    int main() 
    { 
     animal *ptr; 
     ptr = new animal; 
     ptr = new animal [2]; 

     ptr[0].setspeed(9); 
     ptr++->setspeed(13); 

     ptr->print(); 
     cout << ptr[0].getspeed() << endl; 
     cout << ptr[1].getspeed(); 

     return 0; 
    } 
+5

Наилучшая помощь: вкрутите динамические массивы, получите «std :: vector». – Xeo

+0

спасибо, но я хочу понять это (я имею в виду, что я действительно хочу это понять), вот почему я это делаю. Я буду смотреть в «вектор» благодаря – Rave

+2

«ptr = новое животное; ptr = новое животное [2];» Возможно, это просто опечатка, но это утечка памяти. – Duck

ответ

5

Мой C++ ржавый, но вот что я думаю:

ptr++->setspeed(13); 

Это пост-инкремент. ptrпервый оценивается и затем с приращением. Это означает, что setspeed вызывается на исходное значение указателя.

Лично я считаю, что этот стиль кода неприемлем, и я бы уволил любого, кто это пишет. Трудно читать, и его нужно легко читать и понимать.

+0

Не определено поведение. :) – Xeo

+0

И не забудьте уменьшить указатель, чтобы вернуться к началу массива. – Beta

6

Вместо

ptr[0].setspeed(9); 
ptr++->setspeed(13); 

Вы могли бы использовать более интуитивным и даже более правильно

ptr[0].setspeed(9); 
ptr[1].setspeed(13); 

Когда вы делаете ++, вы изменяете значение PTR, поэтому он будет указывать на следующий элемент. Вы должны сохранить указатель на начало массива, чтобы впоследствии удалить его.

Кроме того, ptr ++ увеличивает указатель, но возвращает значение old. Возможно, вы хотели (++ ptr) -> setspeed (13), который будет увеличивать и использовать значение в остальной части выражения.

Что касается вашего другого вопроса, ptr->print() - это то же самое, что и ptr[0].print(), а (ptr+1)->print() - это то же самое, что и ptr[1].print(). Нет встроенного синтаксиса для вызова print() для всех элементов.

6

Хорошо, кто-то указал the memory leak issue вам уже.

Итак, вы выделили массив из двух животных (ptr = new animal [2];) и сохранили указатель на первый в ptr.

+----------+----------+ 
| speed: 0 | speed: 0 | 
+----------+----------+ 
    ^
    | 
    | 
    ptr 

(я не обращая внимания на position_x и position_y, ради пространства)

Затем вы устанавливаете скорость первого до 9 (ptr[0].setspeed(9);):

+----------+----------+ 
| speed: 9 | speed: 0 | 
+----------+----------+ 
    ^
    | 
    | 
    ptr 

Тогда вы делаете что-то очень странное.

ptr++->setspeed(13); 

Зачем вы это делаете, я не знаю. Не делай этого. Я не шучу. Я могу понять, что означает этот код, но я бы никогда не написал ничего подобного. Он служит только для того, чтобы посеять путаницу.

Но давайте притворимся, что это разумная вещь, чтобы сделать какое-то время ... ptr++ увеличивает указатель и возвращает старое значение.

+----------+----------+ 
| speed: 9 | speed: 0 | 
+----------+----------+ 
    ^  ^
     |   | 
     |   | 
    result  ptr 
    of ptr++ 

... а затем она устанавливает скорость животного, на который указывает, что результат до 13.

+-----------+----------+ 
| speed: 13 | speed: 0 | 
+-----------+----------+ 
    ^  ^
     |   | 
     |   | 
    result  ptr 
    of ptr++ 

Наконец, ptr->print() печатает животного указываемого ptr, который является второй один.

+0

так что после i do ptr ++, я нахожусь в ptr [1], если я вызываю delete [] ptr, то удаляется только ptr [1], а ptr [0] теперь является линией памяти? – Rave

+0

@Rave: на самом деле, это еще хуже. Вы можете только 'delete []' указатели, которые были предоставлены 'new []', поэтому 'delete [] ptr' теперь, когда он указывает на второе, является неопределенным поведением.Вам нужно уменьшить указатель до начала, чтобы удалить [] '. –

0

Если оператор ++ после переменной (ptr ++), он сначала выполняет оценку, а затем и приращение. Это означает, что это заявление,

ptr++->setspeed(13); 

работает как

ptr->setspeed(13) // ptr point to animal[0] 
ptr++    // ptr point to anima[1] after this statement 

И ++ ptr-> SetSpeed ​​(13) будет работать в обратном направлении.

Теперь вы можете видеть, где проблема. Фактически вы вызываете setpeed (13) на животном [0] и печать вызова() на животном [1].

+0

Остерегайтесь приоритета оператора. Выражение ++ ptr-> setspeed (13) означает ++ (ptr-> setspeed (13)), т.е. увеличивает возвращаемое значение (если оно существует) вызова функции (не проверено, но я проверил эту таблицу [http: //msdn.microsoft.com/en-us/library/126fe14k%28v=vs.71%29.aspx] перед публикацией). – marcus

+0

Да. Это должно быть (++ ptr) -> setspeed (13) –

Смежные вопросы