const_cast<>()
一般的なルールとして、 (ほとんどの場合) 設計上の欠陥が明らかになるため、C++ コードで使用することは悪い習慣と見なされることがよくあります。
私はこれに完全に同意しますが、使用しているケースは何ですか?唯一の解決策const_cast<>()
は何ですか?
皆さんが知っている/遭遇した例をいくつか教えてください。
どうもありがとうございました。
const_cast<>()
一般的なルールとして、 (ほとんどの場合) 設計上の欠陥が明らかになるため、C++ コードで使用することは悪い習慣と見なされることがよくあります。
私はこれに完全に同意しますが、使用しているケースは何ですか?唯一の解決策const_cast<>()
は何ですか?
皆さんが知っている/遭遇した例をいくつか教えてください。
どうもありがとうございました。
const が正しくないレガシー API でのみ使用するようにほとんど設計されています。つまり、非 const インターフェイスを持ち、実際にはインターフェイスで何も変更しない、変更できない関数で使用されます。
他の人が言っているように、その主な目的はconst
、引数を変更しないことがわかっている非定数の正しい関数に渡すためにオブジェクトから削除することです。
コードの重複を回避するためのトリック(マイヤーズによる?)があり、次のようになります。
struct foo
{
const return_type& get(void) const
{
// fancy pants code that you definitely
// don't want to repeat
return theValue; // and got it
}
return_type& get(void)
{
// well-defined: Add const to *this,
// call the const version, then
// const-cast to remove const (because
// *this is non-const, this is ok)
return const_cast<return_type&>(static_cast<const foo&>(*this).get());
}
};
const_cast
volatile
この(物議を醸している)記事で実践されているように、修飾子を削除するためにも使用されます。
通常の使用は「設計上の欠陥」を隠す必要があるためであるというあなたの声明に同意します。
IME の典型的な使用シナリオの 1 つは、C++ を既存の C コードにインターフェイスしようとする場合です。既存の C コードの多くはchar *
、文字列が変更されていない場合でも C 文字列を使用しますが、通常はconst char *
C++ で a に変換されるものとして表されます。これは、通常は const_cast を使用して解決する 2 つの言語間のインピーダンスの不一致です。もちろん、インターフェースしているコードが、渡されたデータを変更することについてのかわいいアイデアを得ていないことを十分に確認する必要があります.
新しく書かれたコードでは臭いがするのはコードだと思いますが、古い C および C++ コードとのインターフェイスには必要悪です。とはいえ、POD 以外のオブジェクトを必要とするコードには非常に注意を払う必要がありますconst_cast
。これは通常、コード レベルではなく設計レベルで解決する必要がある問題だからです。
(私の意見では) 1 つの正当な使用法は、std::set
反復子を使用することです。const
セットで使用されるキーの変更を防ぐために、それらは常にです。キーを変更すると、セットの内部構造が壊れ、未定義の動作が発生します。
ただし、キーが変更されない限り、オブジェクト内の他のデータを変更しても安全です。
次のようなものがあるとしましょうstd::set
:
std::set<MyObject> some_set;
そして、このようなクラス:
class MyObject {
public:
MyObject(const std::string &key)
: key_(key) {}
bool operator<(const MyObject &other) const {
return key_ < other.key_;
}
private:
// ...
// <some other data>
// ...
const std::string key_;
};
上記の例では、キーはすでに constになっているため、オブジェクトを変更してもセットの内部構造を壊すことはできません。
const
通常、セット イテレータからのみ参照を取得できます。
const MyObject &object = *some_set_iterator;
しかし、キーはであるため、参照解除されたイテレータconst
に対して安全です。const_cast
MyObject &object = const_cast<MyObject &>(*some_set_iterator);
これの非常に正当な使用法の1つは、次のようにconstとnon const api(それぞれconstオブジェクトとnon constオブジェクト)の両方がある場合です。
class Bar {
const SomeType& foo() const;
SomeType& foo();
}
次に、両方の関数でコードを複製したくないので、よく使用します
class Bar {
SomeType& foo() {
//Actual implementation
}
const SomeType& foo() const {
return const_cast<Bar*>(this)->foo();
}
};
もちろん、これはfooがconstセマンティクスに違反することを行わないことを前提としています。
はい、もちろん、変更できず、const が正しくない呼び出しコードの場合。データを変更しないことが確実にわかっている関数の呼び出しでのみ使用する必要があることに注意してください。