代码之家  ›  专栏  ›  技术社区  ›  Engineer999

静态转换允许转换对象指针,但不允许转换整数

  •  1
  • Engineer999  · 技术社区  · 6 年前

    为什么静态强制转换允许在指向派生对象或基对象的指针之间进行上转换或下转换,但如果在char*和int*之间进行强制转换,或者在int*到char*之间进行强制转换,则会出现编译错误?

    我认为在对象的不同指针之间进行转换同样糟糕。

    // compiles fine
    class Base {};
    class Derived: public Base {};
    Base * a = new Base;
    Derived * bc = static_cast<Derived*>(a);
    
    // Gives an invalid static cast error during compilation
    char charVar = 8;
    char* charPtr = &charVar;
    int* intPtr = static_cast<int*>(charPtr);
    
    3 回复  |  直到 6 年前
        1
  •  2
  •   Aconcagua    6 年前

    C++是面向性能的。所以只要有一些用例,你可以获得性能,C++将允许你这样做。考虑 std::vector :当然,可以通过功能访问安全元件 at ,为您进行范围检查。但是如果你知道你的指数 在射程范围内(例如在一个for循环中),这些射程检查只是自重。所以你另外得到了(不太安全的) operator[] 只是忽略了这些支票。

    类似地,如果您有一个类型为 Base ,实际上,它可以指向 Derived . 如果有疑问,你会 dynamic_cast Base* Derived* . 但这需要一些开销。但是如果你百分之百确定(无论如何……)子类到底是什么,你会想要这个开销吗?因为有一个自然的(甚至是隐含的!)方式从 导出* 基* ,我们想找个便宜的回来。

    另一方面,完全不相关类型的指针之间没有这种自然的转换(例如 char int 或者两个无关的类),因此没有这样低成本的方法(与 动态铸件 ,当然也不可用)。在两者之间转换的唯一方法是 reinterpret_cast .

    实际上,reinterpret_cast也没有任何成本,它只是将指针解释为一种不同的类型-具有所有风险!和A 重新解释演员 即使失败,如果 static_cast 会被要求(有权阻止“为什么不总是使用…”)的问题:

    class A { int a; };
    class B { };
    class C : public A, public B { };
    
    B* b = new C();
    C* c = reinterpret_cast<C*>(b); // FAILING!!!
    

    从内存布局来看, C 看起来是这样的(即使躲在你身边):

    class C
    {
        A baseA;
        B baseB; // this is what pointer b will point to!
    };
    

    很明显,在 C* B* (任意一个方向),两者都考虑 静态铸造 动态铸件 ,但不是 重新解释演员

        2
  •  2
  •   eerorika    6 年前

    为什么静态投射允许向上投射…

    没有理由阻止上映。事实上,派生指针甚至可以隐式转换为基指针-不需要强制转换(除了在有多个相同类型基的卷积情况下)。派生类对象始终包含基类子对象。

    upcasting特别有用,因为它允许通过使用虚拟函数进行运行时多态性。

    或在指向派生对象或基对象的指针之间向下转换,如下所示

    基指针 可以 指向派生对象的基子对象,作为向上转换的结果。例如:

    Derived d;
    Base *b = &d;
    

    在某些情况下,您可能希望访问派生对象的成员 知道是被人指着的。静态强制转换使这成为可能,而无需花费运行时类型信息。

    编译器通常不可能(在编译时)找出指向对象的具体类型(即指针是否指向子对象,如果指向子对象,容器对象的类型是什么)。程序员有责任确保满足cast的要求。如果程序员无法证明其正确性,那么编写静态转换就是一个错误。

        3
  •  0
  •   einpoklum    6 年前

    那是因为你要做的是重新解释 reinterpret_cast<> 操作员。 static_cast<> 因为指针是 only used for down-casting :

    1. 如果new_type是指向某个类d的指针或引用,而表达式的类型是指向其非虚拟基b的指针或引用,则static_cast将执行向下转换。如果b是d的二义性、不可访问或虚拟基(或虚拟基的基),则此向下转换是不正确的。此类静态\u转换不进行运行时检查,以确保对象的运行时类型实际上是d,并且只有通过其他方式(如实现静态多态性。可以使用dynamic_cast进行安全下投。

    见:

    When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?

    详细讨论何时使用每个铸造操作员。