13

C++ クラスの複数の const プロパティが何らかの中間計算に依存している場合、それらを初期化する最も簡単な方法は何ですか?

たとえば、以下のクラスのコンストラクターを修正するにはどうすればよいですか?

class MyClass {
public:
    const int a;
    const int b;

    MyClass() {
        int relatedVariable = rand() % 250;
        a = relatedVariable % 100;
        b = abs(relatedVariable - 150);
    }
};
4

8 に答える 8

11

C ++ 11では、委任コンストラクターを使用するだけです。

class MyClass
{
public:
    const int a;
    const int b;

private:
    MyClass( int relatedVariable )
      : a( relatedVariable % 100 ),
        b( abs( relatedVariable - 150 ) ) {}

public:
    MyClass() : MyClass( rand() % 250 ) {}
};
于 2013-03-20T22:46:21.593 に答える
6

委任コンストラクターを使用したラウンドアバウトソリューションは次のとおりです。

class MyClass
{
    MyClass(int aa, int bb) : a(aa), b(bb) { }

    static MyClass Maker() { int x = /* ... */; return MyClass(x * 2, x * 3); }

    int const a;
    int const b;

public:
    MyClass(MyClass const &) = default;
    MyClass() : MyClass(Maker()) { }
};
于 2013-03-20T22:23:23.163 に答える
3

これは、たまたまコーディングがあまり進んでいないことを好む私たちにとってはうまくいくでしょう。

class MyClass {
public:

    int iamStupid;      /* K.I.S.S. */

    const int a;
    const int b;

    MyClass()
      : iamStupid(rand() % 250)
      , a(iamStupid % 150)
      , b(abs(iamStupid - 150))
    {}
};

追加のメンバーは、不必要なオーバーヘッドをもたらします。これは、目の前のタスクにとって重要である場合とそうでない場合があります。OTOH、コードは簡単です。

and のiamStupid に宣言することを忘れないでください。(コメントを参照)ab

于 2013-03-20T22:19:01.700 に答える
2

委譲コンストラクターをサポートしていない古いコンパイラーに行き詰まっている場合は、古い言語バージョンに適応した同じアプローチを次に示します。

class MyClassBase {
public:
    const int a;
    const int b;
    MyClassBase(int a, int b) : a(a), b(b) {}
};

class MyClass : public MyClassBase {
    static MyClassBase Maker() {
        int x = rand() % 250;
        return MyClassBase(x % 100, abs(x - 150));
    }
public:
    using MyClassBase::a;
    using MyClassBase::b;

    MyClass() : MyClassBase(Maker()) { }
};
于 2013-03-20T22:48:50.030 に答える
2

あなたはこのようなことをすることができます - きれいではありませんが、トリックをするべきです:

class MyClass {
public:
    const int a;
    const int b;
    static int relatedVariable;
    MyClass() :
        a(setRand()),
        b(relatedVariable)  {}
    static const int setRand()
    {
        relatedVariable = rand() % 250;
        return relatedVariable;
    }
};
int MyClass::relatedVariable = 0;
于 2013-03-20T22:15:49.517 に答える
1

計算を行う中間クラスを導入します。

class ConstCalc {

   public:
    ConstCalc(int related) : rv(related){}

    int a() const { return rv % 100; } 
    int b() const { return abs( rv - 150 ) ; } 

   private:
    const int rv;
};

class MyClass {
public:
    const int a;
    const int b;

    MyClass( const ConstCalc c ) : a( c.a() ), b( c.b() ) {
    }
};
于 2013-03-20T22:13:16.237 に答える
1

Const は、クラスのユーザーと実装者の間の契約です。これは、クラスのユーザーがメンバー変数を変更してはならないことを示しているため、不変のオブジェクト設計が提供されます。それ以外の場合、コンストラクターがその状態を初期化することは問題ありません。とはいえ、これらをプライベート アクセス修飾子の背後に隠し、読み取り専用を許可するアクセサーを提供する方がよい場合があります。const-ness を一時的に削除する正しい方法は、const_cast<> を使用することです。

class MyClass {
public:
   const int a;
   const int b;

MyClass() : a(0), b(0) {
    int relatedVariable = rand() % 250;
    const_cast<int&>(a) = relatedVariable % 100;
    const_cast<int&>(b) = abs(relatedVariable - 150);
}

};

于 2013-03-20T22:26:32.303 に答える
-1

a作成してbプライベートにし、ゲッターを提供して、クラスの外部から値にアクセスすることができます。

class MyClass
{
private:
    int a, b; // private
public:
    int getA() { return a; }
    int getB() { return b; }

    MyClass()
    {
        int relatedVariable = rand() % 250;
        a = relatedVariable % 100;
        b = abs(relatedVariable - 150);
    }
};

または、サブオブジェクト初期化子を使用して、何らかの方法で乱数をキャッシュすることもできます。最適化をオンにすると、生成されたプログラム テキストの一時変数が削除されることさえあります。

class MyClass
{
private:
    int temp; // this is a workaround
public:
    const int a;
    const int b;

    MyClass() : temp(rand() % 250), a(temp % 100), b(abs(temp - 150)) {}
};

サブオブジェクトの構築は、メンバーがクラスで宣言された順序で行われ、初期化リスト内のサブオブジェクトの順序は無視されることに注意してください。

または、怠け者で、最初の乱数のみを保存し、a, bオンデマンドで生成することもできます。

于 2013-03-20T22:26:55.607 に答える