必要性の明確化がなC-スタイルを解釈し、const集
-
23-09-2019 - |
質問
私にと仮定してC-スタイル鋳ることはお勧め)のものでreinterpret_casts?使用後は冷たい印象を覚えると簡単に検索して見たときのための手にかぶりなのでお勧めです。C-スタイルは?
場合鋳造離定数を使用const_cast書きるものconstオブジェクトが未定義は、何の目的であconst_cast?
注意: 知っているBjarneを正しく非難を鋳造とその安全でないものがどの程度の記載を" 醜い 操作することが必要言語形式"に面したこのレベルの鋳造事業者のC++.いをします。お約束いたします。:)
解決
はありません。 Cキャストはconst_cast
の等価、static_cast
、reinterpret_cast
、またはそれらの組み合わせを行うことができます。かなり十分ではなかった場合には、それはまた、は、新しいキャストのないの組み合わせが全く行わないことを少なくとも一つのマイナーなトリックを行うことができます!
元の変数がconst_cast
なしで定義されている場合は、定義された結果とconst
を使用することができますが、あなたが持っているすべては、そのオブジェクトへのconst
ポインタまたは参照です。 OTOH、あなたはconst_cast
を使用するには十分な理由があると思うならば、チャンスはあなたが本当に代わりmutable
を調べる必要があることです。
編集:私は、私は右のオフにそれを言っているはずですが、Cスタイルのキャストがアクセスできないベースクラスに変換することができたとします。例えば、のようなものを考えてみます:
[編集:私は(通常は)コンパイルします何かのコードを更新しています問題を示します。
#include <iostream>
class base1 {
public:
virtual void print() { std::cout << "base 1\n"; }
};
class base2 {
public:
virtual void print() { std::cout << "base 2\n"; }
};
class derived : base1, base2 {}; // note: private inheritance
int main() {
derived *d = new derived;
base1 *b1 = (base1 *)d; // allowed
b1->print(); // prints "base 1"
base2 *b2 = (base2 *)d; // also allowed
b2->print(); // prints "base 2"
// base1 *bb1 = static_cast<base *>(d); // not allowed: base is inaccessible
// Using `reinterpret_cast` allows the code to compile.
// Unfortunately the result is different, and normally won't work.
base1 *bb2 = reinterpret_cast<base1 *>(d);
bb2->print(); // may cause nasal demons.
base2 *bb3 = reinterpret_cast<base2 *>(d);
bb3->print(); // likewise
return 0;
}
reinterpret_cast
sを使用してコードをコンパイルします - しかし、(2のLEST 1での)結果を使用しようとすると、大きな問題が発生します。そして(最大で)から1つのベースオブジェクトが実際にそのアドレスに存在することができ、 - reinterpret_cast
はベース派生オブジェクトとそれがベースオブジェクトの指定されたタイプであるかのようにそれを治療するための試みののアドレスを取り他の缶として扱うしようとしている/大きな問題が発生します。編集:ここでは、クラスはそう何がのの起こる、ほとんどのコンパイラで、最後の2の両方が「ベース1」を出力します可能性があり、彼らは印刷するものを除き、本質的に同一です。 reinterpret_castはそのアドレスであることを起こるものは何でも取り、指定されたタイプとしてそれを使用しようとします。この場合、私は何かの無害が、目に見えるメイクを行う(しようとした)しました。実際のコードでは、結果はおそらくとてもきれいではありません。
Cスタイルのキャストはstatic_castをたい動作します - すなわち、各ので、それは、どこ派生クラス内の各基本クラスオブジェクト「命」を意識だし、結果を調整それが適切な場所でのポイントに調整されていますので、結果のポインタが動作します。
他のヒント
いいえ、Cスタイルのキャストは、状況に応じてreinterpret_cast
s、const-cast
sまたはstatic_cast
sとして機能することができます。彼らは落胆している理由はここにある - あなたはそれが何をするかを確認する詳細については、外観にコードと必要なCスタイルのキャストを参照してください。たとえばます:
const char* source;
int* target = (int*)source;// - acts as const_cast and reinterpret_cast at once
//int* target = retinterpret_cast<int*>source;// - won't compile - can't remove const
覚えているconstキャストが動かけいたしました事を深くお詫びその識別子:
void doit(const std::string &cs)
{
std::string &ms = const_cast<std::string &>(cs);
}
int main()
{
std::string s;
doit(s);
}
なdoitは鋳造かconst、この例では、元の文字列でない定数で定義されます。
更新
大丈夫、こちらのより良い例での利用の場合const_castは全く役に立た.まずは、基底クラスの仮想関数が定数のパラメータ:
class base
{
public:
virtual void doit(const std::string &str);
};
またオーバーライドする仮想機能です。
class child : public base
{
public:
virtual void doit(const std::string &str)
{
std::string &mstr = const_cast<std::string &>(str);
}
};
のための論理構造的なヘルプオーサリング-ツールすることを知 child::doit
のみ呼び出される非定数の文字列( class base
な下に制御できな変更することもできますの変更に署名 child::doit
でなくオーバーライド base::doit
).この場合には、安全キャストに離れconst.
あり、ここにはリスクがあります。うに書くときには、その実行に到達しない child::doit
非定数の文字列をコードが有効になります。その変更のいずれかを維持しつつプログラムからきからの直送の最新バージョンの class base
.
Cスタイルのキャストは、実際にプログラミングのスレッジハンマーです - あなたは基本的にそこ平方ペグが何でこのラウンド穴にフィットしないことをコンパイラに伝えます。その意味で、reinterpret_cast
は非常に似ています。
私はC ++を使用してご覧ください主な利点は - スタイルキャスト演算子は、彼らはあなたがより良いあなたの意図を表現し、あなたがワンではなく、実行することを求めている操作上のいくつかのチェックにまだにコンパイラを許可できるようにするということです万能スタイルのCキャストます。
あなたは、多くの場合、APIはこれを実行する必要がありますという理由だけで、あなたはconst参照を経由して周りのオブジェクトを渡しているような状況に入るconst_cast
-について。
void X(const char *str) { ... }
それは、文字列を変更していないにもかかわらず、あなたは、char *
を期待するC関数にパラメータを渡している関数内。これに対応する唯一の方法はconst_cast
列strになります。
私はない全く正しい、あなたのデザインのものがあることを、多くの場合、この番組、出演者の任意の並べ替えを使用して非常に慎重になるだろうが、時にはあなたはそれが前提としていて、それは見ていペグが正方形としてではないことをコンパイラを説得する必要があります。そうしてあなたはキャスト演算子を使用する必要があります。