0

今、私は運動の問題に直面しました:クラス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;
}

次に、結果は次の図のようになります。 結果の写真

leftとを初期化していないと思いますtop。しかし、私はそれを修正する方法がわかりません。コードに間違いが見つかりません。

4

5 に答える 5

4

コピーコンストラクタは1 rightとをbottom「初期化」するだけでtopleftガベージ値が残ります。

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

次に、この2つのパラメーターコンストラクターには同様の欠陥があります。

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

すべてのデータメンバーを何かに設定する必要があります。そうすれば、コピーコンストラクターを完全に削除して、コンパイラーが合成したコンストラクターにその仕事をさせることができます。

1なぜ引用符が逆になっているのですか?実際には、少なくとも意味的にはすでに初期化されているデータメンバーに値を割り当てているためです。データメンバーを値に初期化するには、コンストラクター初期化リストを使用します。CRect(float left1,float top1) : left(left1), top(top1), right(), bottom() {}

于 2013-03-21T12:39:09.343 に答える
2

コピーコンストラクターCRect(CRect &c)は、左右の初期化に失敗します。コピーコンストラクターはr1、andr2を関数Diagonalとに渡すときに呼び出されますShow

さらに:

  1. コピーコンストラクターを定義する必要はまったくありません。独自に定義しない場合は、デフォルトのものが生成されます。
  2. ShowおよびDiagonalはメンバー関数であるため、パラメーターを取る必要はありません。
于 2013-03-21T12:41:08.663 に答える
1

CRect(float left1,float top1)コンストラクターとコピーコンストラクターのすべてのメンバーを初期化していない。

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

または、copy-constructorを省略して、デフォルトのcopy-constructorがすべてを実行できるようにすることもできます。

もっと

CRect(float left1,float top1)
{
    left=left1;
    top=top1;
    // How about right and bottom ?!
}
于 2013-03-21T12:39:36.957 に答える
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
}
于 2013-03-21T12:42:55.893 に答える
0

私の答えはあなたの質問に直接対処するものではありませんが、コンストラクターで初期化リストを使用してクラスメンバーメンバー変数を初期化する習慣を身に付けたいと思うでしょう。(これは、初期化リストがまだクラスに導入されていない可能性があることを認識していると言います。)

たとえば、次のようにコンストラクタからメンバー変数に値を割り当てる代わりに、次のようにします。

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

...代わりに、次のようにメンバー変数を初期化する必要があります。

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

理由については、C ++ FAQエントリ[10.6]を参照してください。コンストラクターは「初期化リスト」または「割り当て」を使用する必要がありますか?SOのC++初期化リストも同様です。

独自のプログラミングでは、メンバー変数を他の変数タイプとより簡単に区別できるように、メンバー変数に命名規則を採用することを検討することもできます。たとえば、次の代わりに:

private:
    float left;       // no decoration

...2つの一般的な規則のいずれかを使用することを検討してください。

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

これについて詳しくは、SO上のC++のメンバー変数の末尾の下線を参照してください。

于 2013-03-21T14:02:50.743 に答える