static_cast

static_cast conversion

使用了隐式转换和用户定义的转换的结合的方式,进行类型间转换。

Syntax

static_cast < new_type > ( expression )

返回类型为“new_type”的值。

Explanation

只有如下的转换可以使用static_cast来完成,除非这些转换破坏了“constness”或“volatility”。

1)如果有一个从expression到new_type的隐式转换序列,或者expression得到的一个object或一个类型为new_type的引用直接初始化的重载方案能够找到至少一个可执行的函数,那么static_cast<new_type>会返回一个假想的变量Temp,由new_type Temp(expression)完成了初始化;它可能引入了一个隐含的转换调用,new_type的构造函数的调用,或者一个"user-defined conversion operator"的调用。对于一个非引用的new_type, static_cast,static_cast表达式返回的结果object是直接初始化的。

2)如果new_type是某个classD的指针或者引用,那么该表达式的类型是某个“no-virtual ”基类 classB的指针或引用,static_cast执行了“downcast”操作。如果classB是模糊的、不能访问的,或者是classD的虚基类,那么,这个downcast是不符合语法的。这种情况下,static_cast不能做运行时检查来保证object运行时的类型一定是classD。只有通过其它的先决条件,例如实现“static polymorphism”,这种情况下,才能正常运行。安全的downcast方式应该是“使用dynamic_cast.

3) If new_type is an rvalue reference type, static_cast converts the value of glvalue, class prvalue, or array prvalue (until C++17)any lvalue (since C++17) expression to xvalue referring to the same object as the expression, or to its base sub-object (depending on new_type). If the target type is an inaccessible or ambiguous base of the type of the expression, the program is ill-formed. If the expression is a bit field lvalue, it is first converted to prvalue of the underlying type. This type of static_cast is used to implement move semantics in std::move.

4) If new_type is the type void (possibly cv-qualified), static_cast discards the value of expression after evaluating it.

5) If a standard conversion sequence from new_type to the type of expression exists, that does not include lvalue-to-rvalue, array-to-pointer, function-to-pointer, null pointer, null member pointer, function pointer, (since C++17) or boolean conversion, then static_cast can perform the inverse of that implicit conversion.

6) If conversion of expression to new_type involves lvalue-to-rvalue, array-to-pointer, or function-to-pointer conversion, it can be performed explicitly by static_cast.

7) Scoped enumeration(C++11) type can be converted to an integer or floating-point type.

8) A value of integer or enumeration type can be converted to any complete enumeration type.

  • If the underlying type is not fixed, the result is unspecified (until C++17)undefined behavior (since C++17) if the value of expression is out of range (the range is all values possible for the smallest bit field large enough to hold all enumerators of the target enumeration).
  • If the underlying type is fixed, the result is the same as the converting the original value first to the underlying type of the enumeration and then to the enumeration type.

A value of a floating-point type can also be converted to any complete enumeration type.

  • The result is the same as converting the original value first to the underlying type of the enumeration, and then to the enumeration type.

9) A pointer to member of some class D can be upcast to a pointer to member of its unambiguous, accessible base class B. This static_cast makes no checks to ensure the member actually exists in the runtime type of the pointed-to object.

10) A prvalue of type pointer to void (possibly cv-qualified) can be converted to pointer to any object type. If the original pointer value represents an address of a byte in memory that does not satisfy the alignment requirement of the target type, then the resulting pointer value is unspecified. Otherwise, if the original pointer value points to an object a, and there is an object b of the target type (ignoring cv-qualification) that is pointer-interconvertible (as defined below) with a, the result is a pointer to b. Otherwise the pointer value is unchanged. Conversion of any pointer to pointer to void and back to pointer to the original (or more cv-qualified) type preserves its original value.

As with all cast expressions, the result is:

  • an lvalue if new_type is an lvalue reference type or an rvalue reference to function type;
  • an xvalue if new_type is an rvalue reference to object type;
  • a prvalue otherwise.

Two objects a and b are pointer-interconvertible if:

  • they are the same object, or
  • one is a union object and the other is a non-static data member of that object, or
  • one is a standard-layout class object and the other is the first non-static data member of that object, or, if the object has no non-static data members, any base class subobject of that object, or
  • there exists an object c such that a and c are pointer-interconvertible, and c and b are pointer-interconvertible.
union U { int a; double b; } u;
void* x = &u;                        // x's value is "pointer to u"
double* y = static_cast<double*>(x); // y's value is "pointer to u.b"
char* z = static_cast<char*>(x);     // z's value is "pointer to u"

Notes

static_cast may also be used to disambiguate function overloads by performing a function-to-pointer conversion to specific type, as in

std::for_each(files.begin(), files.end(),
              static_cast<std::ostream&(*)(std::ostream&)>(std::flush));

Keywords

static_cast

Example

Run this code

#include <vector>
#include <iostream>
 
struct B {
    int m = 0;
    void hello() const {
        std::cout << "Hello world, this is B!\n";
    }
};
struct D : B {
    void hello() const {
        std::cout << "Hello world, this is D!\n";
    }
};
 
enum class E { ONE = 1, TWO, THREE };
enum EU { ONE = 1, TWO, THREE };
 
int main()
{
    // 1: initializing conversion
    int n = static_cast<int>(3.14);
    std::cout << "n = " << n << '\n';
    std::vector<int> v = static_cast<std::vector<int>>(10);
    std::cout << "v.size() = " << v.size() << '\n';
 
    // 2: static downcast
    D d;
    B& br = d; // upcast via implicit conversion
    br.hello();
    D& another_d = static_cast<D&>(br); // downcast
    another_d.hello();
 
    // 3: lvalue to xvalue
    std::vector<int> v2 = static_cast<std::vector<int>&&>(v);
    std::cout << "after move, v.size() = " << v.size() << '\n';
 
    // 4: discarded-value expression
    static_cast<void>(v2.size());
 
    // 5. inverse of implicit conversion
    void* nv = &n;
    int* ni = static_cast<int*>(nv);
    std::cout << "*ni = " << *ni << '\n';
 
    // 6. array-to-pointer followed by upcast
    D a[10];
    B* dp = static_cast<B*>(a);
 
    // 7. scoped enum to int or float
    E e = E::ONE;
    int one = static_cast<int>(e);
    std::cout << one << '\n';
 
    // 8. int to enum, enum to another enum
    E e2 = static_cast<E>(one);
    EU eu = static_cast<EU>(e2);
 
    // 9. pointer to member upcast
    int D::*pm = &D::m;
    std::cout << br.*static_cast<int B::*>(pm) << '\n';
 
    // 10. void* to any type
    void* voidp = &e;
    std::vector<int>* p = static_cast<std::vector<int>*>(voidp);
}

 

Output:

n = 3
v.size() = 10
Hello world, this is B!
Hello world, this is D!
after move, v.size() = 0
*ni = 3
1
0

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值