0
class BaseClass {
public:
  BaseClass(const byte *buff, long size) { 
     // Some Computation
  }
};

class DerivedClass: public BaseClass {
public:
  std::vector<byte> filebuff;
  long buff_size;
  DerivedClass(): BaseClass(/*How should I send stuff here?*/) 
  { 
  }
  /*return type??*/  cal_func(){
   // Some computation involving file descriptors.
   // Store result in filebuff. Store size of filebuff in buff_size.
    return /*what??*/;
  }
}

次の解決策しか思いつきません。

 DerivedClass(): BaseClass(&filebuff[0], cal_func) 

上記の場合、filebuff の長さを返す関数 func() を作成します。私は filebuff が単なるアドレスであるという事実に依存しているため、コンパイラが func の計算値を最初にスタックに置くか、最初の引数である filebuff に置くかは問題ではありません。

これが正しい方法かどうか教えてください。最初の引数がアドレスではなく、関数 func で実行される計算を必要とするその他の計算値でない場合、どのように処理するのが最善でしょうか?

4

2 に答える 2

2

問題はfilebuff、基本クラスのコンストラクターが非静的メンバーのコンストラクターの前に呼び出されるため、初期化される前に使用しようとしていることです。ここで継承を構成に置き換えることが最善の解決策であるというildjarnに同意します。

class BaseClass {
public:
  BaseClass(const byte *buff, long size) { 
     // Some Computation
  }
};

class YourClass {
public:
  std::vector<byte> filebuff;
  long buff_size;
  BaseClass base;

  DerivedClass()
    : /* initialize filebuff and buff_size */, base(&filebuff[0], buff_size) {}
};

メンバーは、クラス定義に表示される順序で初期化されるため、ベースのコンストラクターfilebuffに渡すことができます。buff_size

「C++: メンバー クラスの初期化順序」という質問に対するこの回答も参照してください。

于 2013-03-29T23:49:01.870 に答える
2

他の誰かが書いたクラス (たとえば、別のライブラリ) を 2 つの引数を取るクラスを、よりクリーンなインターフェイスを持つ別のクラス (自分が書いたクラス) でラップしようとしているようです。私は正しいですか?

提案された解決策は、他の基本クラスから派生し、派生クラスを使用して、基本クラスに入れられる引数を格納することです。上記のアプローチの問題は、基本クラスのコンストラクターを呼び出すときに、派生クラスがまだ完全に構築されていないことです (つまり、filebuff と bufsize が何かに初期化されていることを保証できません)。

別のアプローチをお勧めします。派生する代わりに、次のように、基本クラスと 2 つのデータ メンバーを含む WrapperClass があります。

class Wrapper {
public:
  Base base;
  std::vector<byte> filebuff;
  long buff_size;
  Wrapper();
}

したがって、ラッパー クラスのコンストラクターでは、次のことができます。

WrapperClass::WrapperClass() {
  //do whatever you want to initialize filebuff and buffsize here
  calcfunc();

  //now pass them in to your base class
  base = Base(filebuff, buffsize);
}

[編集]

上記の解決策では、基本クラスにデフォルトのコンストラクター、つまり Base() があることを前提としています。そうでない可能性があり、作成できない可能性があります。baseその場合、メンバー変数をデフォルトで初期化する方法がないため、上記のコードはコンパイルされません。別の方法として、 Base メンバーを直接使用する代わりに、 、 または などの Base クラスへのポインタ、またはそのようなメカニズムBase*を使用することもできます。std::unique_ptr<Base>このようにして、Base クラスが初期化されるタイミングを正確に制御します。そう:

//class definition
class Wrapper {
public:
  std::unique_ptr<Base> base;
  std::vector<byte> filebuff;
  long buff_size;
  Wrapper();
}

//...

//constructor implementation
WrapperClass::WrapperClass() {
  //do whatever you want to initialize filebuff and buffsize here
  calcfunc();

  //now pass them in to your base class
  base = new Base(filebuff, buffsize);
}
于 2013-03-29T23:37:59.360 に答える