C++でクラスコンストラクターを再設計していて、不特定のブール値をキャッチするために必要です。他のすべてのパラメーターにはデフォルト値を使用しましたが、私の理解では、boolはtrueまたはfalseにのみ初期化できます。これらのケースはどちらもクラスで意味があるので、デフォルト値からの変更のチェックをどのように処理する必要がありますか?
現実には、これはできません。ブール値にはtrueまたはfalseのいずれかの値があり、初期化していない場合は、ランダムにtrueまたはfalseになり、プログラムの実行またはそのクラスの割り当てごとに異なる可能性があります。
より多くのオプションを備えたタイプが必要な場合は、列挙型を定義してください。
typedef enum MyBool {
TRUE,
FALSE,
FILENOTFOUND
} MyBool;
トライステートブールはダークサイドへのパスです。トライステートブールは怒りにつながります。怒りは憎しみにつながります。憎しみは苦しみにつながります。
トライステートブール値を使用しないことをお勧めします。
代わりに、最初のブール値が「初期化」されている(またはより適切には「既知」である)かどうかに、1つの追加のブール値を使用します。
class Prisoner : public Person
{
...
bool is_veredict_known;
bool is_guilty;
}
判決がまだわかっていない場合、囚人が本当に有罪かどうかはわかりませんが、コードはさまざまな状況を区別できます。もちろん、憲法はis_guiltyのデフォルト値がfalseであることを保証していますが、それでも... :)
ちなみに、クラス不変条件には次のものが含まれている必要があります。
assert(is_veredict_known || !is_guilty);
boost :: tribool または多分 boost :: optional <bool> が必要なようです。
それが必要な場合は、初期化されていない可能性のある値の概念を表す値を作成します。
template <typename T>
struct Maybe {
Maybe() : m_hasValue(false) {}
bool HasValue() const { return m_hasValue; }
T& Value() { ThrowIfFalse(m_hasValue); return m_value; }
const T& Value() const { ThrowIfFalse(m_hasValue); return m_value; }
void SetValue( _In_ const T& value) { m_value = value; m_hasValue = true; }
private:
bool m_hasValue;
T m_value;
};
これで、必要な3つの状態すべてを表すことができます。
class SomeType {
...
Maybe<bool> m_myBool;
}
C++では、bool
は0または1のいずれかの1ビットの情報です。3つの可能な状態を表したいので、もう1ビットの情報が必要です。 2つの一般的な手法があります。
bool
値を使用して、値が「デフォルト」であるかどうかを示します。私はおそらくオプション1を選択します。
大きなboost :: optionalを使用してください。そして、boolだけでなく、他のすべての場所で、初期化されていないダーティな値を使用しました。これは次のように使用されます。
void function(optional<int> value) {
if (value)
std::cout << "value is defined: " << value.get() << "\n";
else
std::cout << "value is not defined\n";
}
オプションを返す関数の例を次に示します。
struct MapClass {
map<string,int> m_map;
optional<int> getValue(string key) {
optional<int> result = none;
if (m_map.find(key) != m_map.end())
result = m_map[key];
return result;
}
}
struct Bool { //guaranteed initialized bool
bool v;
Bool() : v(false) {}
operator bool() const { return v; }
bool& operator=(const bool val){ return v = val; }
};
Bool値が実際に初期化されているかどうかを示す別のプライベートメンバーを持つことができます。
よくわかりませんが、やってみます...
一部の値を指定しないままにする集約初期化子がある場合、デフォルト値が適用されます。その場合、boolのデフォルトはfalseになります。クラスでは、「デフォルト」値は初期化されません。つまり、任意の値であり、実行ごとに変わる可能性があります。
Boolが変更されたかどうかに関心がある場合は、2番目のboolがデフォルトでfalseになるように追跡するか、3つの可能な状態を表す列挙型を使用するのが最善のオプションです。本当に3つの状態が必要な場合は、ブール値は必要ありません。
あなたは本当にできません。次に、2番目のコンストラクターを提供できますか?
class MyClass {
public:
MyClass(bool bFlag); // <-- not default
MyClass(void); // <-- default
};
ブール値の代わりに、列挙型を使用します。たとえば、魔法のレベルを制御するには:
enum {
MY_ENUM_NO_MAGIC,
MY_ENUM_SOME_MAGIC,
MY_ENUM_MORE_MAGIC
} MagicLevel;
次に、コンストラクターにパラメーターMagicLevel magic = MY_ENUM_NO_MAGIC
を受け入れさせます。
class aclass
{
<stuff> lots of other things
bool mybool
bool ismyboolinit
void setmybool(bool b)
{
mybool = b;
ismyboolinit = true;
}
}
関数やクラスを使用している場合は、それらをオーバーロードするだけです。
すなわち:
class thing
{
public:
void f1(bool); // bool input
void f1(int = 3); // default with out bool being known
private:
// stuff
};
void thing::f1 (bool hasAFace)
{
if(hasAFace)
f1(0);
if(!hasAFace)
f1(1);
}
void thing::f1 (int tri)
{
bool actionTime;
if(tri == 1)
actionTime = true;
else if(tri == 0)
actionTime = false;
else
//input defualt action here.
}
//そしてそこに行きます。また、オーバーロードされた関数を使用できるクラスを用意する必要はありません。