很少有人怀疑在C ++中使用运算符

时间:2010-11-05 16:29:43

标签: c++ operator-overloading casting

我们知道reinterpret_cast可以将任何指针类型转换为任何其他指针类型。关于这个演员运算符我想问的问题是:

  1. reinterpret_cast如何运作,允许reinterpret_cast工作的神奇之处(内部实现)是什么?
  2. 使用reinterpret_cast时如何确保安全?据我所知,它不能保证安全铸造,那么使用reinterpret_cast?
  3. 时要采取什么预防措施
  4. 此运算符的实际用法是什么。我没有在我的专业编程经验中遇到过这种情况,其中我无法使用此运算符。除了通常的int * to char *之外的任何实际示例都将非常有帮助和赞赏。
  5. 关于铸造操作员的另一个问题:
    投射操作符(static_castdynamic_castconst_castreinterpret_cast)都称为Operators,即根据我的理解,所以它是正确的声明让那个casting operators cannot be overloaded unlike most other operators(我知道不是所有的操作员都可以超负荷而且我知道哪些不可​​能(除了QI要求,请不要惹恼我)只是我有这个怀疑,因为他们是运营商,标准对这些做了什么?

9 个答案:

答案 0 :(得分:4)

  1. 没有魔法。 reinterpret_cast通常只意味着(至少尝试)将您在此地址找到的内容视为我指定的类型。该标准对可能与之不同的内容进行了足够的定义,但它很少(如果有的话)确实存在。
  2. 在少数情况下,你可以从像歧视的联盟那样获得安全感。例如,如果您正在读取网络数据包,并且读取的内容足以看到您收到的是TCP数据包,那么您可以(公平地)安全地从reinterpret_cast到{{IPHdr进行TCPHdr 1}}(或者您碰巧使用的任何名称)。编译器不会(再次,通常)做很多事情 - 任何安全都取决于您实施和执行。
  3. 我使用了我在2)中描述的代码,处理不同类型的网络数据包。
  4. 对于你的最后一个问题:你可以为一个班级重载:

    class XXX { 
    public:
        operator YYY() { return whatever; }
    };
    

    这可以用于一般的转换 - 无论是通过static_cast,C样式转换,还是隐式转换。 C ++ 0x允许您添加explicit限定符,因此它不会用于隐式转换,但是仍然无法区分static_cast和C样式的转换。

答案 1 :(得分:2)

reinterpret_cast通常会让你做一些非常糟糕的事情。在转换指针的情况下,它将允许从一种类型转换到另一种类型,绝对没有理由认为这应该起作用。这就像说“相信我,我真的想要这样做”。究竟是什么从一个系统到另一个系统是不可预测的。在你的系统上,它可能只是复制位模式,而在另一个模式上,它可以以某种(可能有用的)方式对它们进行转换。

e.g。

class Foo {
    int a;
};

class Bar {
    int a;
};

int main() {

  Foo a;

  // No inheritance relationship and not void* so must be reinterpret_cast 
  // if you really want to do it
  Bar *b = reinterpret_cast<Bar*>(&a);

  char buffer[sizeof(Bar)];

  Bar *c = reinterpret_cast<Bar*>(buffer); // alignment?

}

无论情况如何,都会很乐意让你这样做。有时,如果你正在对事物进行低级操作,那么这实际上可能就是你想做的事情。 (想象一下缓冲区的char *转换为用户定义的类型)

潜在的陷阱是巨大的,即使在最简单的情况下,如缓冲区,对齐可能是一个问题。

在Linux上使用dlsym(),能够将void*转换为函数指针是很有用的,这在C ++中是未定义的行为。 (某些系统可能使用单独的地址空间或不同大小的指针!)。这只能通过C ++中的reinterpret_cast来完成。

答案 2 :(得分:2)

首先,目前还不清楚“非标准指针”是什么意思。我认为你的前提是有缺陷的。令人高兴的是,它似乎并没有影响到这些问题。

“它如何运作?”好吧,正如您可以从名称中猜测的那样,意图只是改变位模式的解释,可能适当地扩展或缩短。这是一种类型的变化,其中位模式保持不变但是解释和因此概念值被改变。并且它与保持概念值的类型变化形成对比(例如int转换为double),同时根据需要更改位模式以保持概念值。但是大多数reinterpret_cast的情况都有实现定义的效果,所以对于那些情况,你的编译器可以做任何想做的事情 - 不一定保留bitpattern - 只要它被记录下来。

“如何确保安全”这是关于了解编译器的功能,以及避免 reinterpret_cast。 : - )

“实际用途是什么”。主要是关于恢复在面向C的代码中丢失的类型信息,其中void*指针用于排序模拟多态。

干杯&amp;第h。,

答案 3 :(得分:1)

  1. reinterpret_cast仅适用于指针。它的工作方式是它只留下指针的值并改变它的假定类型信息。它说,“我知道这些类型并不等同,但我希望你假装现在这是指向T2的指针。”当然,如果你使用T2指针并且它没有指向T2,这可能会导致任何数量的问题。

  2. 关于reinterpret_cast的保证非常少,这就是为什么要避免它。您实际上只允许从T1转换为T2然后再回到T1并且知道,在给定一些假设的情况下,最终结果将与您开始时的结果相同。

  3. 我能想到的唯一一个是将char *转换为unsigned char *。我知道底层表示在我的实现中是相同的,所以我知道演员是安全的。我不能使用静态转换,因为它是指向缓冲区的指针。实际上,你会发现现实世界中reinterpret_cast的合法使用很少。

  4. 是的,他们是运营商。 AFAIK你无法覆盖它们。

答案 4 :(得分:1)

reinterpret_cast的一个“实际”用法。

我有一个班级,其成员不应被阅读。以下示例

class ClassWithHiddenVariables
{
private:
    int a;
    double m;
public:
    void SetVariables(int s, int d)
    {
        a = s;
        m = d;
    }
}; 

此类在应用程序的千位中使用而没有问题。

现在,由于某种原因,我希望在一个特定部分看到成员。但是,我不想触及现有的类。所以违反规则如下。

创建具有相同位模式和公共可见性的另一个类。这里原始类包含int和double。

class ExposeAnotherClass
{
public:
    int a_exposed;
    double m_exposed;
};

如果要查看ClassWithHiddenVariables对象的成员,请使用reinterpret_cast转换为ExposeAnotherClass。示例如下

ClassWithHiddenVariables obj;
obj.SetVariables(10, 20.02);    
ExposeAnotherClass *ptrExposedClass;
ptrExposedClass = reinterpret_cast<ExposeAnotherClass*>(&obj);  
cout<<ptrExposedClass->a_exposed<<"\n"<<ptrExposedClass->m_exposed;

我认为这种情况不会发生在现实世界中。但这只是对reinterpret_cast的一种解释,它将对象视为位模式。

答案 5 :(得分:0)

reinterpret_cast告诉编译器“闭嘴,它是T *类型的变量”并且没有安全性,除非它实际上是T *类型的变量。在大多数实现中,没有做任何事情 - 变量中的相同值被传递到目标。

您的类可以将转换运算符设置为任何类型的T *,并且这些转换将在某些条件下隐式调用,或者您可以使用static_cast显式调用它们。

答案 6 :(得分:0)

我在Windows编程中经常使用reinterpret_cast。消息处理使用需要转换为正确类型的WPARAM和LPARAM参数。

答案 7 :(得分:-1)

  

我们知道reinterpret_cast可以   将任何非标准指针强制转换为   另一个非标准指针。

几乎,但不完全是。例如,您无法使用reinterpret_cast将const int*转换为int*。为此,您需要const_cast

  

reinterpret_cast是如何工作的,什么是魔法(内部的   实施)允许   reinterpret_cast工作?

根本没有魔力。最终,所有数据都只是字节。 C ++类型系统只是一个抽象层,告诉编译器如何“解释”每个字节。 reinterpret_cast类似于普通的C-cast,因为它只是说“与类型系统一起地狱:将这些字节解释为X型而不是Y型!”

  

使用reinterpret_cast时如何确保安全?据我所知,它   不保证安全铸造,所以   使用时要采取什么预防措施   的reinterpret_cast?

嗯,reinterpret_cast本来就很危险。除非你真的知道自己在做什么,否则不应该使用它。请尝试使用static_cast。如果使用static_cast,C ++类型系统将保护您不会做任何太危险的事情。

  

此运算符的实际用法是什么。我还没有   在我的专业人士遇到过它   编程经验,其中我   没有使用这个可能无法解决   operator.Any实际例子   从通常的int *到char *将是   非常有帮助和赞赏。

它有很多用途,但通常这些用途有些“先进”。例如,如果要创建链接块的内存池,并在块本身上存储指向空闲块的指针,则需要reinterpret_castT*到{{1}的块。将块解释为指向下一个块的指针,而不是块本身。

答案 8 :(得分:-1)

reinterpret_cast非常相当于C风格的演员表。它不保证任何东西;它是让你做你需要的,希望你知道你在做什么。

如果您希望确保安全,请使用dynamic_cast,因为它就是这样做的。如果无法安全地完成强制转换,dynamic_cast将返回NULL或nullptr(C ++ 0x)。

使用诸如static_cast,dynamic_cast等“cast creat”进行强制转换不能重载​​。直接转换可以,例如:

class Degrees
{
public:
    operator double() { ... }
};