0

ユーザーにいくつかのコンストラクターを提供するc ++のヘッダーファイルがあります(これは必須です):

#ifndef IMANDEL_H_
#define IMANDEL_H_

class IMandel{

public:
    IMandel();
    IMandel(int aWidth, int aLength);
    IMandel(int threads, int aWidth, int aLength);
    //other stuff!
private:
    int max_iterations, thread_count, height, width;
    int* buffer; 
};

#endif

したがって、対応する cpp ファイルでは、これらのコンストラクターをそれぞれ実装しています。

//default constructor
IMandel::IMandel(){
    height = 10000;
    width = 10000;

    //this code segements gets repeated in every constructor! Messy!
    max_iterations = 255;
    thread_count = 1;
    buffer = new int[width*height];
}

IMandel::IMandel(int aWidth, int aLength){
    width = aWidth;
    height = aLength;

     //this code segements gets repeated in every constructor! Messy!
    max_iterations = 255;
    thread_count = 1;
    buffer = new int[width*height];
}

IMandel::IMandel(int threads, int aWidth, int aLength){
    thread_count = threads;
    width = aWidth;
    height = aLength;

     //this code segements gets repeated in every constructor! Messy!
    max_iterations = 255;
    buffer = new int[width*height];
}

ご覧のとおり、私のコンストラクターは正常ではありません。どこでもコードのチャンクが繰り返されています。これはひどいことです。

Java では、コンストラクターを使用して相互に呼び出すことで、この問題の解決策を見つけました。基本的に、次のようなコンストラクターを再利用します (Java の例)。

public myClass(){
    this(1, 10000, 10000);
}

public myClass(int aWidth, int aLength){
   this(1, aWidth, aLentgh);
}

public myClass(int threads, int aWidth, int aLength){
   thread_count = threads;
   width = aWidth;
   height = aLength;
   max_iterations = 255;
   buffer = new int[width*height];
}

この Java の例でわかるように、さまざまなコンストラクター間でコードが繰り返されていません。質問:

  1. C++ でこれと同じ効果を達成する方法はありますか?
  2. もしそうなら、どのように?サンプルを提供できますか?
  3. そうでない場合、問題を解決するためにどのような解決策をお勧めしますか?
4

3 に答える 3

7

実際の解決策は、使用している C++ のバージョンによって異なります。

C++03では、すべてのコンストラクターが呼び出す関数を作成するのが一般的な(ただし不完全です - 下部の便利なコメントを参照)方法です。init()3 つのコンストラクターはすべて、次のような関数を呼び出す 1 行にすることができます。

void IMandel::init(int threads, int aWidth, int aLength){
    thread_count = threads;
    width = aWidth;
    height = aLength;

     //this code segements gets repeated in every constructor! Messy!
    max_iterations = 255;
    buffer = new int[width*height];
}

//default constructor
IMandel::IMandel(){
    init( 1, 10000, 10000 );
}

IMandel::IMandel(int aWidth, int aLength){
    init( 1, aWidth, aLength );
}

IMandel::IMandel(int threads, int aWidth, int aLength){
    init( threads, aWidth, aLength );
}

C++11では、@chris がコメントしたように、コンストラクターは他のコンストラクターを呼び出すことができます。次の方法でコンストラクタを変更できます。

//default constructor
IMandel::IMandel()
: IMandel( 1, 10000, 10000 )
{
}

IMandel::IMandel(int aWidth, int aLength)
: IMandel( 1, aWidth, aLength )
{
}

IMandel::IMandel(int threads, int aWidth, int aLength){
    thread_count = threads;
    width = aWidth;
    height = aLength;

     //this code segements gets repeated in every constructor! Messy!
    max_iterations = 255;
    buffer = new int[width*height];
}
于 2013-03-17T19:12:33.153 に答える
3

どのソリューションを採用するかは、具体的なケースによって異なります。

現在のクラス定義は次のとおりです。

class IMandel
{
public:
    IMandel();
    IMandel(int aWidth, int aLength);
    IMandel(int threads, int aWidth, int aLength);
    //other stuff!
private:
    int max_iterations, thread_count, height, width;
    int* buffer; 
};

これを定義する方法は次のとおりです。

class IMandel
{
public:
    IMandel( int aWidth = 10000, int aLength = 10000, int threads = 1 );
    //other stuff!
private:
    int max_iterations, thread_count, height, width;
    std::vector<int> buffer;
};

これにより、引数の順序を除いて、最初に持っていた明らかなコンストラクターが引き続き提供されることに注意してください。

物事を必要以上に複雑にする必要はありません。つまり、KEEP IT SIMPLEです。ただし、他の C++03 の手段には、共通のinit関数 (該当する場合、ここではありません) と共通の人工基本クラスが含まれます。その他の C++11 手段には、コンストラクター転送が含まれます。


ちなみに、元のコードが「3 つのルール」に違反していたことに注意してください。つまり、コピーを禁止するか明示的にサポートする必要がありましたが、それができませんでした。上記の単純化には、その問題はありません。理由がわかりますか?

于 2013-03-17T19:20:18.123 に答える
2

コンパイラが C++11 の委譲コンストラクターをサポートしている場合、コンストラクター内のコードの重複を減らすことができます。ただし、あなたの場合、コンストラクターの引数にデフォルト値を指定するだけでよいようです。

#ifndef IMANDEL_H_
#define IMANDEL_H_

class IMandel{

public:
    IMandel(int aWidth = 10000, int aLength = 10000, int threads = 1);
private:
    int max_iterations, thread_count, height, width;
    int* buffer; 
};

#endif

IMandel::IMandel(int aWidth, int aLength, int threads)
: max_iterations(255)
, thread_count(threads)
, height(aLength)
, width(aWidth)
, buffer(new int[width*height])
{
}

上記のコンストラクターは、あなたが示した3つのすべてを行います。また、メモリを自分で管理する代わりにvector<int>forを使用することを検討してください。buffer

于 2013-03-17T19:16:59.613 に答える