1

以下のコードでは、 class のオブジェクトに渡される引数に基づいて、 kap(class )の 2 つのオーバーロードされたコンストラクターのいずれかを呼び出すことを意図しています。opacitymaterial

class opacity{
 private:
  int mode;
  double kap_const;
  double kappa_array[10][10];

 public:
  opacity(double constkap);  // picking the constructor sets the mode
  opacity(char* Datafile);
  double value(double T, double P); // will return a constant or interpolate
};

opacity::opacity(double constkap):mode(1){
  kap_const = constkap;
}

opacity::opacity(char* Datafile):mode(2){
  // read file into kappa_array...
}

class Matter {
 public:
  Matter(int i, double k, char* filename); // many more values are actually passed
  opacity kap;
  int x;  // dummy thing
  // more variables, call some functions
};

Matter::Matter(int i, double k, char * filename)
 :x(k>0? this->kap(x): this->kap(filename) ) {
  // ... rest of initialisation
 }

ただし、これは機能しません。

test.cpp: In constructor 'Matter::Matter(int, double, char*)':
test.cpp:32:21: error: no match for call to '(opacity) (void*&)'
test.cpp:32:42: error: no match for call to '(opacity) (char*&)'
test.cpp:32:44: error: no matching function for call to 'opacity::opacity()'
test.cpp:32:44: note: candidates are:
test.cpp:20:1: note: opacity::opacity(char*)
test.cpp:20:1: note:   candidate expects 1 argument, 0 provided
test.cpp:16:1: note: opacity::opacity(double)
test.cpp:16:1: note:   candidate expects 1 argument, 0 provided
test.cpp:4:7: note: opacity::opacity(const opacity&)
test.cpp:4:7: note:   candidate expects 1 argument, 0 provided

私が最初に試したのは、

Matter::Matter(int i, double k, char * filename)
 :kap(k>0? k: filename) {   // use k<0 as a flag to read from filename
  // ... rest of initialisation
}

同様の質問で指摘されているように、コンパイル時の理由から「三項演算子の結果は常に同じ型でなければならない」ため、失敗しました(ただし、そこでは説明されていないようです)。

さて、コンストラクターが受け取るべきMatter引数に基づいてコンストラクターをオーバーロードすることも、洗練されていない解決策になりますkapが、これは(1)特にMatterコンストラクターが多くの変数を取り、多くのアクションを実行するため、非常に洗練されていません (したがって、多くのコードがコンストラクターの初期化リストの一部を変更するためだけに複製されます)、(2)異なるコンストラクターを持つkap別のクラスが使用されている場合、これは手に負えなくなる可能性があります: N c'torsを持つMクラスの場合、1 つはNになります。 ^ Mの組み合わせ...Matter

誰かが提案や回避策を持っていますか? 前もって感謝します!

4

4 に答える 4

4

opacity にコピー コンストラクターがある場合は、初期化リストでこれを実現できます。これにより、デフォルトのコンストラクターを回避できますが、コピーのコストがかかります。

  Matter::Matter(int i, double k, char * filename)
     :kap( ( 0 < k ) ? opacity(k) : opacity( filename ) ) { ... }
于 2011-10-06T18:38:07.503 に答える
1

デフォルトのコンストラクターを追加してopacity(0無効なモードを示すためにモードをに設定する可能性があります) kap、コンストラクター本体でに割り当てる必要があります。

Matter::Matter(int i, double k, char * filename) {
  if(k > 0)
    kap = opacity(k);
  else
    kap = opacity(filename);
}

パラメータkはランタイム値です。型とオーバーロードの結果を実行時の値に依存させることはできません。

于 2011-10-06T18:26:19.700 に答える
1

コピーのオーバーヘッドを回避し、C++0x コンパイラがあると仮定すると、 opacity にmove コンストラクターopacityを指定し、ロジックに基づいてstatic 関数に のインスタンスを提供さkapせ、返された temporary でメンバーを初期化することができますopacity

kappa_arrayのようなポインターを作成したいと思うでしょうauto_ptr<double>。ただし、このデータがタイトループで使用される場合、可動性による節約は、局所性とポインターの逆参照のコストと比較して疑わしい場合があります。

opacity& get_opacity(double k, char * filename) {
    if(k > 0)
        return opacity(k);
    else
        return opacity(filename);
}

Matter::Mater(int i, double k, char * filename)
    : kap(get_opacity(k, filename) {
   //...
}

opacity::opacity(opacity&& other)
    : mode(other.mode),
      kap_const(other.kap_const),
      kappa_array(std::move(kappa_array)) { }

これについて私をテストしないでください。私は移動セマンティクスと右辺値参照についてはかなり新しいです...

于 2011-10-06T18:44:19.123 に答える
0

演算子の結果は単一の型しかないため、三項演算子を使用して関数のオーバーライドを選択することはできません。異なるブランチが異なるタイプを持っている場合、それらは結果タイプに強制変換されるか、コンパイル時エラーが発生します。http://en.wikipedia.org/wiki/%3F:#Result_typeを参照してください

それは本当に他の方法ではありえませんでした。型はコンパイル時にコンパイラーによって認識される必要がありますが、操作の結果は実行時まで認識されません。

于 2011-10-06T18:52:40.550 に答える