私はライブラリをプログラミングしています(そのため、上記のすべてのクラスに完全にアクセスできます)。 2つのクラス(A
とB
)は基本的に同じであり、実装のみが異なるため、簡単に相互に変換できます。ただし、B
型の引数をA
のコンストラクタの1つに渡すか、B
をA
に暗黙的にキャストして変換する場合、好ましい。説明する2つのコード例:
キャストの使用:
class A
{
public:
int c[3];
operator B() const
{
//return B(...);
}
};
class B
{
public:
int a, b, c;
operator A() const
{
//return A(...);
}
};
コンストラクターの使用:
class A
{
public:
A(const B& b)
{
//...
}
int c[3];
};
class B
{
public:
B(const A& a)
{
//...
}
int a, b, c;
};
両方のアプローチの長所と短所は何ですか?どちらを使用するべきですか?そして、誰かがライブラリを拡張し、いくつかのコンストラクタでexplicit
キーワードを使用した場合、いくつかの問題が発生する可能性がありますか?
このような変換を実行する一般的な方法は、コンストラクターを使用することです。型キャスト演算子は、プリミティブ型(ほとんどの場合bool
または効果的にブール値のように機能するもの)への変換、または追加のコンストラクターを追加できない型にのみ効果的に使用されます。
型キャスト演算子は、コンストラクタを変換するよりも予期しないときに呼び出されるリスクがはるかに大きいため、通常は細心の注意を払って処理する必要があります。
標準ライブラリで型変換演算子を使用する有益な例の1つは、std::string
からstd::string_view
への変換です。単純なコードを考えてみましょう:
std::string s("string");
std::string_view sv(s);
std::string_view
のコンストラクタはstd::string
を受け入れず、変換は演算子で実行されます
operator std::string_view<...>() const noexcept;
std::string
クラス内。
このデザインの動機は、以下に引用するMarshall Clowの this document (P0254R2)にあります。
string_view
が提案されたとき...string
とstring_view
の間の接続はすべてstring_view
で行われていました。string_view
には以下が含まれます:
string
からの暗黙の変換- メンバー関数
to_string
。新しい文字列を作成します。これは逆だと思います。
string_view
はstring
について何も認識していない必要があり、string
は型間の変換を処理する必要があります。具体的には、string
には以下が必要です。
string_view
への暗黙の変換string_view
からの明示的なコンストラクター。根拠:
string_view
を基本的な語彙タイプとして使用すると、効率が向上します。...
string
からstring_view
を作成するのは簡単です。したがって、暗黙的に変換されます。string_view
からstring
を作成するのは安価ではないため、明示的に行う必要があります。
- 他の文字列タイプのサポート。
...独自の文字列クラスからデータを出力することを検討してください...
home_string
。operator<<
の実装はかなりの作業量であり、iostream
sインフラストラクチャ全体の合理的に完全な知識が必要です。一方、string_view
を使用すると、誰かが次のように書くことができます。template<...> ostream<...>& operator<<(ostream<...>& os, const home_string<...>& str) { return os << string_view<...>(str); }
すべてのフォーマットなどを「無料」で入手できます。