5

メンバーを持つクラスとconst、追加の値が入力された別のコンストラクターを呼び出す1つのコンストラクターがあります。通常、これにはコロン初期化子を使用できますが、関数は複雑(printf/のsprintfような)であり、スタックで変数を使用する必要があります、したがって、コンストラクターの本体でこれを実行*thisし、新しいオブジェクトに割り当てを使用する必要があります。しかしもちろん、これは無効です。私のメンバー変数はconstです。

class A
{
public:
    A(int b) : b(b), c(0), d(0) // required because const
    {
        int newC = 0;
        int newD = 0;
        myfunc(b, &newC, &newD);
        *this = A(b, newC, newD); // invalid because members are const

        // "cannot define the implicit default assignment operator for 'A', because non-static const member 'b' can't use default assignment operator"
        // or, sometimes,
        // "error: overload resolution selected implicitly-deleted copy assignment operator"
    };
    A(int b, int c, int d) : b(b), c(c), d(d) { };

    const int b;
    const int c;
    const int d;
};

A a(0);

(代入演算子を明示的に削除していません。)メンバーを公開したいのですが、変更できないようにしたいので、メンバーをconstと宣言しました。

怖いキャストを使用したり、メンバーの性格を強制的に無効にしたりせずに、この問題を解決するための標準的な方法はありますconstか?ここでの最良の解決策は何ですか?

4

4 に答える 4

2

ヘルパー関数を作成するのはどうですか。

class A
{
    static int initializor(int b) { int n; myfunc(b, &n); return n; }
public:
    explicit A(int b_) : b(b_), c(initializor(b_)) { }
    A(int b_, int c_)  : b(b_), c(c_)              { }

    // ... as before ...
};
于 2012-08-19T23:27:00.907 に答える
2

パラメータークラスを追加して、C++11コンストラクター委任または基本クラスのいずれかを使用できます。

struct parameters {
    int b; int c; int d;
    parameters(int b): b(b), c(), d() {
        myfunc(b, &c, &d);
    }
};

// constructor delegation
class A {
public:
    A(int b): A(parameters(b)) { }
    A(parameters p): b(p.b), c(p.c), d(p.d) { }
};

// base/wrapper
class ABase {
    ABase(parameters p): b(p.b), c(p.c), d(p.d) { }
};

class A: public ABase {
public:
    A(int b): ABase(parameters(b)) { }
};
于 2012-08-20T00:46:33.383 に答える
1

Kerrek SBの答えが好きですが、あなたの場合、メンバーごとに個別の初期化関数を簡単に作成できないという複雑さがあります。

その場合、別の解決策は、メンバーを基本クラスに移動し、その基本クラスを非constメンバーを持つヘルパークラスで初期化することです。初期化コードはヘルパークラスのコンストラクターに移動され、問題なく割り当てることができます。

class A_init
{
  public:
    A_init(int b)
    {
      // do whatever you like with c and d:
      c = ...;
      d = ...;
    }

    int c; // Note: non-const
    int d; // Note: non-const
};

class A_base
{
   public:
     A_base(int b, A_init init) : b(b), c(init.c), d(init.d) {}
     A_base(int b, int c, int d) : b(b), c(c), d(d) {}

     const int b;
     const int c;
     const int d;
};

class A : public A_base
{
  public:
    A(int b) : A_base(b, A_init(b)) {}
    A(int b, int c, int d) : A_base(b, c, d) {}
};

アクセスを制限したい場合は、プライベートに切り替えて友達A_initを宣言できます。A

于 2012-08-20T00:47:03.767 に答える
0

myfuncさまざまなmem-initializerから設定して使用できるように、結果をどこに配置しますか?デフォルトの引数ではどうですか?

class A
{
private:
    struct InitData;
public:
    A(int b, InitData data=InitData());
    A(int b, int c, int d) : b(b), c(c), d(d) { };

    const int b;
    const int c;
    const int d;
};

struct A::InitData
{
    int setup(int b);
    int c;
    int d;
};

inline int A::InitData::setup(int b)
{
    myfunc(b, &c, &d);
    return b;
}

inline A::A(int b_, InitData data)
    : b(data.setup(b_)),
      c(data.c),
      d(data.d)  {}

A a(0);

作成されたタイプはプライベートであり、変換されないため、誤って使用したり悪用したりするリスクはほとんどありません。

于 2012-08-19T23:46:10.267 に答える