需要澄清C风格,重新解释和const cast [英] Need clarifications in C-style, reinterpret, and const casts

查看:289
本文介绍了需要澄清C风格,重新解释和const cast的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以假设C风格的cast(不鼓励)只是reinterpret_casts?



如果使用const_cast抛出const,并且写入的话,那么使用后者在视觉上是醒目的,并且很容易在寻找讨厌的cast时搜索。一个原来的const对象是未定义的,const_cast的目的是什么?



我知道Bjarne正确地谴责铸造操作,甚至达到了一个丑陋的操作应该有一个丑陋的句法形式的程度。因此在C ++中的铸造操作符的冗长。所以我会尽量减少使用。诺言。 :)

解决方案

否。 AC cast可以做相当于 const_cast static_cast reinterpret_cast ,或其组合。



p>如果原始变量未定义 const ,您可以使用 const_cast 定义结果, const 指针或对该对象的引用。 OTOH,如果你认为你有一个很好的理由使用 const_cast ,可能是你应该真正查找 mutable



编辑:我想我应该马上说,但C风格的转换可以转换为一个不可访问的基类。例如,考虑类似:



  #include< iostream> 

class base1 {
public:
virtual void print(){std :: cout< base 1 \\\
; }
};

class base2 {
public:
virtual void print(){std :: cout< base 2\\\
; }
};

类派生:base1,base2 {}; //注意:私有继承

int main(){
derived * d = new derived;
base1 * b1 =(base1 *)d; // allowed
b1-> print(); // printsbase 1
base2 * b2 =(base2 *)d; //也允许
b2-> print(); // printsbase 2

// base1 * bb1 = static_cast< base *>(d); //不允许:base是不可访问的

//使用`reinterpret_cast'允许代码编译。
//不幸的是,结果是不同的,通常不会工作。
base1 * bb2 = reinterpret_cast< base1 *>(d);
bb2-> print(); //可能导致鼻腔恶臭。

base2 * bb3 = reinterpret_cast< base2 *>(d);
bb3-> print(); //同样
return 0;
}

代码使用 reinterpret_cast s将编译 - 但试图使用结果(两者中的至少一个)将导致一个主要问题。 reinterpret_cast 使用派生对象的 base 地址,并尝试将其视为指定类型的基础对象,至多)一个基础对象可以实际存在于该地址,试图将其视为另一个可以/将导致重大问题。编辑:在这种情况下,类基本上是相同的,除了他们打印,所以尽管任何可能发生,大多数编译器,最后两个将打印出基本1。 reinterpret_cast接受在该地址发生的任何事情,并尝试将其用作指定的类型。在这种情况下,我(试图)使某事无害,但可见。在实际代码中,结果可能不会那么漂亮。



C风格的转换将像static_cast那样工作,如果代码使用公共继承而不是私有 - 即它知道在派生类中每个基类对象生活在哪里,并调整结果,所以每个结果指针将工作,因为它已被调整到指向正确的地方。


Am I right in assuming that C-style casts (which are discouraged) are nothing but reinterpret_casts? Using the latter is visually striking and easy to search when looking for nasty casts, and hence it's recommended over C-style casts?

If casting away const using const_cast and writing to a originally const object is undefined, what is the purpose of const_cast?

Note: I know that Bjarne rightly condemns casting operations that they are unsafe and even goes to the extent of stating "An ugly operation should have an ugly syntactic form." and hence the verbosity of casting operators in C++. So I'll try to minimize their usage. Promise. :)

解决方案

No. A C cast can do the equivalent of a const_cast, a static_cast, a reinterpret_cast, or a combination thereof. In case that wasn't quite enough, it can also do at least one minor trick that no combination of the newer casts can do at all!

You can use const_cast with defined results if the original variable is defined without const, but all you have is a const pointer or reference to that object. OTOH, if you think you have a good reason to use a const_cast, chances are that you should really look up mutable instead.

Edit: I suppose I should have said it right off, but a C-style cast can convert to an an inaccessible base class. For example, consider something like:

[Edit: I'm updating the code to something that'll compile and (usually) demonstrate problem. ]

#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;
}

The code using the reinterpret_casts will compile -- but attempting to use the result (of at lest one of the two) will cause a major problem. The reinterpret_cast takes the base address of the derived object and attempts to treat it as if it was the specified type of base object -- and since (at most) one base object can actually exist at that address, trying to treat it as the other can/will cause major problems. Edit: In this case, the classes are essentially identical except for what they print, so although anything could happen, with most compilers, both of the last two will print out "base 1". The reinterpret_cast takes whatever happens to be at that address and tries to use it as the specified type. In this case, I've (tried to) make that do something harmless but visible. In real code, the result probably won't be so pretty.

The C-style cast will work like a static_cast would if the code had used public inheritance instead of private -- i.e. it's aware of where in the derived class each base class object "lives", and adjusts the result, so each resulting pointer will work because it's been adjusted to point at the right place.

这篇关于需要澄清C风格,重新解释和const cast的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆