0

我有这个类“Point”,它以 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");
    }
4

6 回答 6

4

那是因为您没有初始化成员变量,而是更改了传递给构造函数的变量的副本。因此,您看到垃圾值xy(类版本)从未初始化。您应该将其更改为:

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

此外,您永远不会srand()在任何地方调用 - 您需要在某些时候执行此操作以正确播种随机生成器。

于 2013-04-24T14:00:07.210 回答
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; 
于 2013-04-24T14:02:44.080 回答
0

因为您正在更改构造函数中的临时变量(同一范围内的名称冲突)。尝试:

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

但这完全忽略了给构造函数的参数。但既然现在你知道如何区分不同范围的变量,我相信你可以从这里继续下去。

于 2013-04-24T13:59:39.943 回答
0

您的默认构造函数什么都不做。它甚至不初始化值,这意味着它们将具有未指定的值。

您的构造函数采用两个参数只是分配给参数,因为它们的名称会影响成员的名称。

于 2013-04-24T14:01:50.887 回答
0

您遇到了“名称冲突”。在这个函数中

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

分配时,编译器不知道您指的是哪个 x。语言规则会说应该分配输入参数 - 但你不应该依赖它 - 因为它不必要地令人困惑。

一个好的做法是对成员变量采用命名约定。两种常见的方法是在成员前面加上“m”或“_”。我个人喜欢“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:: ),则这是不良类设计的标志。

于 2013-04-24T14:05:19.160 回答
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; }
于 2013-04-24T14:25:28.627 回答