Constructor Privateを宣言する以外は、特定のC ++クラスの構造を禁止する他の方法ですか?
-
26-10-2019 - |
質問
いくつかのクラスがあるとします const Reference メンバー変数と私は特定のタイプの構造を禁止したいと思います。それで、私はConstructorを宣言します プライベート. 。もちろん、コンストラクターはすべてを初期化する必要があります const Reference クラスのメンバー変数。ただし、そうすることで、奇妙に見えるコードが得られます。
class A {
};
class B {
B(const A& a): host(a) {}
private:
B():host(A()) {} // This is ugly and not needed !!
const A& host;
};
コンストラクターをプライベートで宣言する以外に、特定の建設タイプを禁止する別の方法はありますか?コンパイラにコンストラクターを書きたくありません。
解決
これを定義しないでください:
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
でオブジェクトを作成します char
また class B
、幸いなことに、または残念ながらできます 暗黙的に に変換 int
, 、次に、それらを無効にすることができます:
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&)'
他のヒント
ただ除外してください。カスタムコンストラクターを提供するとすぐに、他のコンストラクターは自動生成されていません(コピーコンストラクターを除く)。
禁止したい場合 どれか 構築 - 静的メンバーのみを持つクラスで終わる - あなたは単にできる 宣言する プライベートではなく、プライベートとしてコンストラクター 定義 それ。このようなクラスは、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
, 、誰もがそれらをインスタンス化しないことを知っていると想定されています。
C ++ 11ソリューションを投稿します。 消去 コンストラクター。
class B {
B() = delete;
B(const A& a): host(a) {}
private:
const A& host;
};
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;
};