6

Cスタイルのキャスト(推奨されていません)はreinterpret_castsに過ぎないと思いますか?後者を使用すると、視覚的に印象的で、厄介なキャストを探すときに簡単に検索できるため、Cスタイルのキャストよりもお勧めしますか?

const_castを使用してconstをキャストし、元々constオブジェクトに書き込むことが定義されていない場合、const_castの目的は何ですか?

注: Bjarneは、キャスト操作が安全ではないことを正しく非難し、「醜い操作は醜い構文形式である必要があります」とさえ述べていることを知っています。したがって、C++でのキャスト演算子の冗長性。だから私はそれらの使用を最小限に抑えるようにします。約束。:)

4

5 に答える 5

5

いいえ。ACキャストは、、、、、、またはそれらの組み合わせと同等のことを行うことができますconst_cast。それだけでは不十分な場合は、新しいキャストの組み合わせではまったくできない、少なくとも1つのマイナーなトリックを実行することもできます。static_castreinterpret_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;
}

sを使用するコードreinterpret_castはコンパイルされますが、結果(少なくとも2つのうちの1つ)を使用しようとすると、大きな問題が発生します。は、派生オブジェクトreinterpret_castベースアドレスを取得し、指定されたタイプのベースオブジェクトであるかのように処理しようとします。また、(多くても)1つのベースオブジェクトが実際にそのアドレスに存在できるため、他のオブジェクトと同じように処理しようとします。 /大きな問題を引き起こします。編集:この場合、クラスは印刷するものを除いて基本的に同一であるため、何でも可能ですがほとんどのコンパイラでは、最後の2つは両方とも「ベース1」を出力します。reinterpret_castは、そのアドレスにあるものをすべて取得し、指定されたタイプとして使用しようとします。この場合、私はそれを無害であるが目に見えるものにすることを試みました。実際のコードでは、結果はおそらくそれほどきれいではありません。

Cスタイルのキャストは、コードがプライベートではなくパブリック継承を使用した場合のstatic_castのように機能します。つまり、派生クラスのどこに各基本クラスオブジェクトが「存在」するかを認識し、結果を調整するため、結果の各ポインターは適切な場所を指すように調整されているため、機能します。

于 2010-02-27T08:16:05.073 に答える
1

いいえ、Cスタイルのキャストは、状況に応じてreinterpret_casts、const-casts、またはsとして機能できます。static_castこれが彼らが落胆している理由です-あなたはコードで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
于 2010-02-27T08:14:44.993 に答える
1

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ではないため、未定義の動作はありません。

アップデート

さて、これはconst_castを使用することが完全に無価値ではない場合のより良い例です。まず、constパラメーターを受け取る仮想関数を持つ基本クラスから始めます。

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コードのロジック/構造により、 const以外の文字列でのみ呼び出されることがわかります(class base制御下にないため、コードを変更したり、署名を変更したりすることはできません。これにより、child::doitオーバーライドされなくなります。base::doit)。この場合、constを捨てても安全です。

はい、これは危険です。おそらくそれを書くとき、実行がchild::doit非定数文字列で到達することは決してなく、コードは有効であることは事実です。ただし、プログラムを維持している間、または最新バージョンのを再構築して取得したときに、状況が変わる可能性がありますclass base

于 2010-02-27T08:17:20.050 に答える
0

const_castconstタイプから削除するために使用されます。削除することもできvolatileます。オブジェクトが実際にそうであるconst場合、結果を書き込むことはできず、それでも明確に定義された動作になります。ただし、昇格された場合const(関数に渡されてから、非const T関数にconst_cast戻されても問題ありません。(ここでconst詳細情報を見つけました)

reinterpret_cast constタイプからまたはタイプから削除することはできませんvolatile

も参照してください

于 2010-02-27T08:13:00.213 に答える
0

Cスタイルのキャストは、実際にはプログラミングの大ハンマーです。基本的に、あそこの四角いペグは、何があってもこの丸い穴に収まるとコンパイラに伝えます。その意味で、reinterpret_cast非常に似ています。

C ++スタイルのキャスト演算子を使用することで私が目にする主な利点は、意図をより適切に表現できることと、コンパイラーが、ワンサイズフィットではなく、実行するように要求している操作をチェックできることです。 -すべてのスタイルCキャスト。

に関してconst_cast-APIでこれを行う必要があるという理由だけで、const参照を介してオブジェクトを渡すという状況に陥ることがよくあります。たとえば、Cスタイルの文字列を処理する関数Xがあるとします。

void X(const char *str) { ... }

char *その関数内では、文字列を変更していなくても、を期待するC関数にパラメーターを渡します。これに対応する唯一の方法はconst_caststrです。

あらゆる種類のキャストを使用する場合は非常に注意が必要です。多くの場合、これはデザインに問題があることを示していますが、見ているペグが想定したほど正方形ではないことをコンパイラに納得させる必要がある場合があります。その場合にのみ、キャスト演算子を使用する必要があります。

于 2010-02-27T08:15:28.803 に答える