6

const参照メンバー変数を持つクラスがあり 、特定のタイプの構築を禁止したいとします。したがって、それに応じたコンストラクターをprivateと宣言します。もちろん、コンストラクターは、クラスのすべてのconst参照 メンバー変数を初期化する必要があります。ただし、そうすると、奇妙なコードになります。

class A {
};

class B {
  B(const A& a): host(a) {}
private:
  B():host(A()) {}   // This is ugly and not needed !!
  const A& host;
};

コンストラクターをプライベートとして宣言する以外に、特定の構築タイプを禁止する別の方法はありますか?コンパイラーにコンストラクターを作成させたくありません。

4

4 に答える 4

14

単にこれを定義しないでください:

B():host(A()) {}   // This is ugly and not needed !!

つまり、以下はあなたがやりたいことをするはずです:

class B {
  B(const A& a): host(a) {}
private:
  //B():host(A()) {}   // This is ugly and not needed !!
  const A& host;
};

パラメーターを受け取るコンストラクターを定義した場合、デフォルトのコンストラクターはコンパイラーによって生成されないという考え方です。つまり、上記のクラスのインスタンスをデフォルトで作成することはできません

 B b1; //error - needs default constructor which doesn't exist!
 B b2(a); //ok - only way to create an instance!

C++11ソリューション

C ++ 11では、次のように特定のコンストラクターを生成しないようにコンパイラーに明示的に指示できます。

struct B
{
     B(const A &a) {}

     B() = delete;      //disable
};

それだけでなく。以下で説明するように、それ以上のものがあります。

今興味深い部分

選択したタイプのコンストラクターを選択的に無効にすることもできます。これにより、さらに面白くdeleteなります。このことを考慮、

struct A
{
       A (int) {}
};

このクラスのオブジェクトは、int引数だけでなく、暗黙的にに変換される任意の型で作成できますint。例えば、

A a1(10);  //ok
A a2('x'); //ok - char can convert to int implicitly

B b; 
A a3(b); //ok - assume b provides user-defined conversion to int

ここで、何らかの理由で、クラスのユーザーがまたはAを使用してオブジェクトを作成したくないとします。これは、幸運にも不幸にも暗黙的にに変換でき、次のように無効にできます。charclass Bint

struct A
{
     A(int) {}
     A(char) = delete;      //disable
     A(const B&) = delete;  //disable
};

今ここに行きます:

A a1(10);  //ok
A a2('x'); //error

B b; 
A a3(b); //error - assume (even if) b provides user-defined conversion to int

オンラインデモ: http: //ideone.com/EQl5R

エラーメッセージは非常に明確です。

prog.cpp:9:5:エラー:削除された関数'A :: A(char)'
prog.cpp:10:5:エラー:削除された関数'A :: A(const B&)'

于 2011-09-06T09:18:41.107 に答える
11

そのままにしておいてください。カスタムコンストラクターを指定するとすぐに、他のコンストラクターは自動生成されません(コピーコンストラクターを除く)。

静的メンバーのみを持つクラスで終わるような構築を禁止したい場合は、コンストラクターをプライベートとして宣言するだけで、定義することはできません。このようなクラスがC++で役立つことはめったにありません(インスタンスを作成できないため)。私が考えることができる唯一の目的は、トレイトクラスを実装することです。

template <typename T>
struct type_to_color {
    static char const* value() { return "blue"; }

private:
    type_to_color();
};

template <>
struct type_to_color<int> {
    // Integers are red!
    static char const* value() { return "red"; }

private:
    type_to_color();
}

char const* char_color = type_to_color<char>::value();
char const* int_color  = type_to_color<int>::value();

ただし、これは非常にまれです。特性クラスはC ++に豊富にありますが、コンストラクターをとして宣言することはprivateありません。インスタンス化しないことを誰もが知っていると想定されています。

于 2011-09-06T09:18:45.267 に答える
2

C++11ソリューションを投稿します。コンストラクターを削除します。

class B {
  B() = delete;
  B(const A& a): host(a) {}
private:
  const A& host;
};
于 2011-09-06T09:29:54.043 に答える
0

Konrad Rudolphが言ったように、カスタムコンストラクターを提供するとすぐに、他のコンストラクターは自動生成されません(コピーコンストラクターを除く)。

したがって、他のオプションは次のとおりです。

コンストラクターをプライベートとして宣言します(クラスから継承できないようにします)が、定義を提供しないでください。

class B {
public:
  B(const A& a): host(a) {}
private:
  B(); // not implemented!
  const A& host;
};

または、C ++ 11では、R。MartinhoFernandesが次のように述べています。

class B {
public:
  B() = delete;
  B(const A& a): host(a) {}
private:
  const A& host;
};
于 2011-09-06T09:36:53.407 に答える