为什么我没有成功初始化类中的私有数据成员?

时间:2013-03-21 12:34:47

标签: c++ oop class

现在,我面临一个运动问题:处理类CRect中的一些数据。但我的结果与我的预期不同。

我的代码如下:

#include<iostream>
#include<cmath>
using namespace std;
class CRect
{
public:
    void Diagonal(CRect one)
    {
        float l;
        l=sqrt( (one.right-one.left)*(one.right-one.left)+(one.bottom-one.top)*(one.bottom-one.top) );
        cout<<"The length is "<<l<<endl;
    }
    void Show(CRect one)
    {
        cout<<"("<<one.left<<","<<one.top<<")"<<"   ";
        cout<<"("<<one.right<<","<<one.bottom<<")"<<endl;
    }
    CRect(float left1,float top1,float right1,float bottom1)
    {
        left=left1;
        top=top1;
        right=right1;
        bottom=bottom1;
    }
    CRect(float left1,float top1)
    {
        left=left1;
        top=top1;
    }
    CRect(CRect &c)           
    {
        right=c.right;
        bottom=c.bottom;
    }
private:
    float left,top,right,bottom;
};

int main()
{
    CRect r1(10,10,20,20);
    CRect r2(0,0);
    r2=CRect(r1);
    r1.Show(r1);
    r1.Diagonal(r1);
    r2.Show(r2);
    r2.Diagonal(r2);
    return 0;
}

然后,结果如下图: the result picture

我认为我尚未初始化lefttop。但是,我不知道如何纠正它。我在代码中找不到错误。

5 个答案:

答案 0 :(得分:4)

您的复制构造函数仅“初始化” 1 rightbottomtopleft留下垃圾值:

CRect(CRect &c)           
{
    right=c.right;
    bottom=c.bottom;
}

接下来,这两个参数构造函数有类似的缺陷:

CRect(float left1,float top1)
{
    left=left1;
    top=top1;
}

您必须将所有数据成员设置为某些内容。如果这样做,您可以完全删除复制构造函数,并让编译器合成一个工作。

1 为什么倒置逗号?因为您实际上正在为数据成员分配值,至少在语义上已经初始化了。要将数据成员初始化为值,请使用构造函数初始化列表: CRect(float left1,float top1) : left(left1), top(top1), right(), bottom() {}

答案 1 :(得分:2)

您的复制构造函数CRect(CRect &c)无法初始化左侧和顶部。当您将r1r2传递给函数DiagonalShow时,将调用复制构造函数。

此外:

  1. 您根本不需要定义复制构造函数。如果您没有定义自己的默认值,则会生成默认值。
  2. ShowDiagonal是成员函数,不需要参数。

答案 2 :(得分:1)

您尚未初始化CRect(float left1,float top1)构造函数和复制构造函数中的所有成员。

CRect(const CRect &c) 
{
    right=c.right;
    bottom=c.bottom;
    top=c.top;
    left=c.left;
}

甚至可以省略你的拷贝构造函数,并允许默认的拷贝构造函数做任何事情。

更多

CRect(float left1,float top1)
{
    left=left1;
    top=top1;
    // How about right and bottom ?!
}

答案 3 :(得分:0)

查看你的拷贝构造函数

CRect(CRect &c)           
{
    right=c.right;
    bottom=c.bottom;
}

应该是

CRect(CRect &c)           
{
    right=c.right;
    bottom=c.bottom;
    top=c.top;
    left=c.left
}

答案 4 :(得分:0)

我的回答并未直接解决您的问题,但您希望养成在构造函数中使用初始化列表来初始化类成员成员变量的习惯。 (我说这可以识别您的课程中可能尚未引入初始化列表。)

例如,代替 值分配给构造函数中的成员变量,如下所示:

CRect(float left1, float top1)
{
    left=left1;
    top=top1;
}

...您应该 初始化 您的成员变量,如下所示:

CRect(float left1, float top1)
    : left(left1), top(top1)
{
}

为什么,请参阅C ++常见问题解答条目[10.6] Should my constructors use "initialization lists" or "assignment"? 以及SO上的C++ initialization lists

在您自己的编程中,您可能还需要考虑为成员变量采用命名约定,以便更容易地将它们与其他变量类型区分开来。例如,而不是:

private:
    float left;       // no decoration

...考虑使用两种常见惯例之一:

private:
    float left_;      // trailing underscore
    float m_left;     // leading 'm_'

有关详情,请参阅SO上的Trailing underscores for member variables in C++