2013-04-24 6 views
0

У меня есть этот класс «Точка», который принимает значения x и y в качестве аргументов. Однако мне нужно создать конструктор, который инициализирует их случайными значениями. Я точно не знаю, как это делается. Вот мой код: Я создал конструкторы, но я получаю значения, которые абсурдны, даже когда я устанавливаю x и y.Как создать конструктор, который инициализирует координаты случайными значениями?

#include <iostream> 
#include <cmath> 
#include <ctime> 

    using namespace std; 
    class Point 
    { 
    private: 
     double x; 
     double y; 

    public: 

     double get_x() 
     { 
      return x; 
     } 
     void set_x (double x) 
     { 
      this->x = x; 
     } 
     double get_y() 
     { 
      return y; 
     } 
     void set_y(double y) 
     { 
      this->y = y; 
     } 
     double distanceTo(Point p) 
     { 
      double x2 = p.get_x(); 
      double y2 = p.get_y(); 
      return sqrt(pow(x-x2,2) + pow(y-y2,2)); 
     } 
     Point(double x, double y) 
     { 
      x = rand()*1.0/RAND_MAX * 100; 
      y = rand()*1.0/RAND_MAX * 100; 
     } 
     Point(){}; 


    }; 

    void main() 
    { 
     Point a(1.2,0.5); 
     Point b; 
     b.set_x(1); 
     b.set_y(1); 
     cout << a.distanceTo(b); 
     system ("Pause"); 
    } 
+0

не называют аргументы методов таки членов класса. Это сбивает с толку и подвержено ошибкам – David

ответ

0

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

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

также:

  • это лучше передать ценности, не собирается менять в функции, как постоянная
  • вы можете пройти doubleпо ссылке, не значение
  • использование списки инициаторов вместо присваивания в теле конструктора
  • при использовании постоянных ссылок здесь вам не нужно для разрешения имен, потому что вы не можете изменить постоянные значения, поэтому компилятор будет изменять переменный-член

Код:

class Point 
{ 
public: 
    Point() : 
     x(rand()*1.0/RAND_MAX * 100), 
     y(rand()*1.0/RAND_MAX * 100) 
    { 

    } 

    Point(const double& x, const double& y) : 
     x(x), 
     y(x) 
    { 

    } 

private: 
    double x, y; 

}; 


int main() 
{ 
    Point pt(42, 3.14); 
    Point pt_random; 
} 

же в функциях аксессоры:

double GetX() const { return x; } 
    void SetX(const double& x) { Point::x = x; } 
+0

* SIGH *, вы могли бы просто скопировать/вставить мой код и отредактировать. Извините, я не понимаю, что вы пытаетесь мне сказать, потому что я попробовал это и все еще даю мне такие значения, как 1.633e + 0.234 – XxXunderage

+0

Вот код: http://pastebin.com/TgkvYW1Z. – Drop

0

Поскольку вы изменяете временные переменные в конструкторе (столкновение имен в той же области). Попытка:

Point(double x, double y) 
{ 
    Point::x = rand()*1.0/RAND_MAX * 100; 
    Point::y = rand()*1.0/RAND_MAX * 100; 
} 

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

+1

'this-> x' будет более распространенным и понятным. – pmr

+1

@pmr - Не знаю. Я предпочитаю этот синтаксис. Разве это не добавляет производительности штрафных (разыменование)? Я знаю, что это может быть оптимизировано компилятором, но вы никогда не уверены в этом. –

+0

Интересная точка. Я никогда не думал об этом с точки зрения производительности. Определенно стоит проверить. – pmr

4

Это потому, что вы не инициализируете переменные-члены, а изменяете копию переменных, которые передаются в конструктор. Следовательно, вы видите значения мусора, поскольку x и y (версии классов) никогда не инициализируются. Вы должны изменить это:

Point() 
{ 
    x = rand()*1.0/RAND_MAX * 100; 
    y = rand()*1.0/RAND_MAX * 100; 
} 

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

+0

Так что же я должен изменить? Я изменил свою инициализацию на то, что вы написали, я получил «Point :: Point»: никакая перегруженная функция не принимает 2 аргумента » – XxXunderage

0

Ваш конструктор по умолчанию ничего не делает. Он даже не инициализирует значения, что означает, что они будут иметь неопределенное значение.

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

+0

Я не понимаю, что я должен изменить, чтобы добиться того, что я упомянул в сообщении ... Пожалуйста, не стесняйтесь редактировать мой код – XxXunderage

0

изменение

Point(){}; 

в

Point() 
{ 
    x = rand()*1.0/RAND_MAX * 100; 
    y = rand()*1.0/RAND_MAX * 100; 
} 

также я бы посоветовал изменить свои аргументы \ члены имя, чтобы избежать ошибок. Я лично хотел бы использовать m_ для участников:

private: 
    double m_x; 
    double m_y; 
+0

Это ничего не решает, извините ... – XxXunderage

0

Вы получаете «имя столкновения». При этой функции

Point(double x, double y) 
    { 
     x = rand()*1.0/RAND_MAX * 100; 
     y = rand()*1.0/RAND_MAX * 100; 
    } 

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

Хорошей практикой является принятие соглашения об именах для переменных-членов. Два общих - это префикс членов с «m» или «_». Мне нравится «м» лично.

Тогда ваш код становится:

class Point 
{ 
    public: 
     double mX; 
     double mY; 

    Point(double x, double y) 
    { 
     mX = rand()*1.0/RAND_MAX * 100; 
     mY = rand()*1.0/RAND_MAX * 100; 
    } 
} 

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

Некоторые из приведенных выше ответов также являются правильными, но это признак плохого дизайна класса, если у вас есть имена областей видимости (например, Point ::) в простых функциях.

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