初学者的总结:函数指针、强制类型转换

文章目录

  • 1、指针 * 号的位置总结
  • 2、顶层/底层const
  • 3、函数指针
    • 3.1 最简单的例子
    • 3.2 函数指针作为函数返回数据:
    • 3.3 typedef、using简化函数指针,以及函数指针数组:
  • 4、强制类型转换
    • 4.1 reinterpret_cast
    • 4.2 static_cast、void*
    • 4.3 dynamic_cast
    • 4.4 const_cast
    • 4.5 dynamic_pointer_cast、lexical_cast、duration_cast

1、指针 * 号的位置总结

int *a,b;                               //代表指针a,整数b
int* a,b;                               //同上
int * a,b;                              //同上

2、顶层/底层const

指针本身是一个对象,它又可以指向另外一个对象。所以有两个定义:

  1. 顶层const:指针本身是常量
  2. 底层const:指针所指的对象是常量

执行对象copy的时候,顶层const不受影响,底层const的限制不能忽视,他们必须同时拥有同样的底层const资格或者两个对象的数据类型必须能够转换才行,一般来说非常量可以转换为常量,反之则不行。

const int &r = ci;                      //底层const,用于声明引用的都是底层const
const int* p = &value;                  //底层const,p指向的内容不变,
//此时可以   p = &other_value
//不可以     *p=123;

int * const q = &value;                 //顶层const,q指向的地址不变,地址里面的内容可以变
const int tmp = 42;                     //顶层const
//不可以     p = &other_value
//可以       *p=123;

const详解

3、函数指针

c语言函数指针定义形式:返回类型 (*函数指针名称)(参数类型,参数类型,参数类型,…);

c++函数指针的定义形式:返回类型 (类名称::*函数成员名称)(参数类型,参数类型,参数类型,….);

函数类型由它的返回值和参数类型决定,与函数名无关

bool length_compare(const string &, const string &);

上述函数类型是:bool (const string &, const string &);
上述函数指针pf:bool (*pf)(const string &, const string &);

3.1 最简单的例子

#include 
using namespace std;

class test {
public:
    int fun(int a, char c){
        cout<<"this is fun call:"<

3.2 函数指针作为函数返回数据:

//如果是非类成员函数,在main函数中把对应的类去掉就行了
#include 
using namespace std;

class test
{
public:
    int fun(int a, char c)
    {
        cout<<"this is fun call:"<

3.3 typedef、using简化函数指针,以及函数指针数组:

#include 
#include 

float add(float a,float b)
{
    printf("%f\n",a+b);
    return a+b;
}
float minu(float a,float b)
{
    printf("%f\n",a-b);
    return a-b;
}

//用pfunType 来表示float(*)(float, float)
typedef float(*pfunType)(float, float);

int main()
{
    pfunType p = &add;//定义函数指针变量
    p(3.33, 2.22);
    pfunType parry[2] = {&add, &minu};//定义函数指针数组
    parry[1](3.33, 2.22);

    using use_function = float(*)(float, float);
    use_function temp = &add;
    temp(123.11,555.1);

    //函数指针作为参数可以定义为:void fun(pfunType p)
    //函数指针作为返回值可以定义为:pfunType fun();

    ///原始函数指针数组为:float (*pfunArry[2])(float, float) = {&add, &minu};
    //double k = pfunArry[0](3.33,2.22);// 调用方式
    return 0;
}

4、强制类型转换

避免使用强制类型转换,因为它干扰了编译器的正常的类型检查,reinterpret_cast尤为明显。static_cast、dynamic_cast也不应该频繁的使用,const_cast在重载函数的上下文中使用无可厚非。否则将错误百出。

4.1 reinterpret_cast

reinterpret_cast作用:

  1. 网络理解:从一个指向函数、对象、类成员函数、类数据成员等等的指针到另外一个不同类型的指针
  2. C++11primer:运算对象的位模式提供较低层次上的重新解释

IBM的C++指南、C++之父Bjarne Stroustrup的FAQ网页和MSDN的Visual C++也都指出:错误的使用reinterpret_cast很容易导致程序的不安全,只有将转换后的类型值转换回到其原始类型,这样才是正确使用reinterpret_cast方式。

int *ip;
char *pc = reinterpret_cast(ip);

我们必须牢记pc的真实对象是一个int类型,否则可能出现运行时的错误,例如:
string str(pc);

4.2 static_cast、void*

特许规则:

虽然不能隐式地将一个左值转换为右值引用,但是可以使用static_cast显示地将一个左值转换为一个右值引用。但是还是建议使用std::move(),使得去查找截断左值的代码变得容易。

一般性规则:

任何具有明确定义的类型转换,只要不包含底层的const,都可以使用static_cast

//i、j都是整形
double t = static(j) / i;       //显示告诉编译器,我们不在乎精度的损失,减少警告

//我们必须确保转换后的类型就是指针所指的类型,否则出现未定义的错误
void *p = &d;                           //任何非常量对象地址都能存入void*
double *tp = static(p);

void *

任何非常量对象地址都能存入void*,以void*的视角来看内存空间,无法访问内存空间的内容,因为我们不知道是什么类型

4.3 dynamic_cast

使用形式:

其中type为一个类类型,并且通常情况下应该含有一个虚函数。
dynamic_cast(e);                 //e必须为一个有效指针
dynamic_cast(e);                 //e必须为一个左值
dynamic_cast(e);                //e必须不是一个左值

在上面所有形式中,需要符合下面三个条件之一就能够转换成功:

  1. e的类型是目标type的公有派生类
  2. e的类型是目标type的公有基类
  3. e的类型是目标type的类型
  4. 可以对一个空指针进行转换,得到的结果也是空指针

否则将会转换失败,得到的结果将是0,并且抛出一个bad_cast的异常

4.4 const_cast

const_cast只能改变运算对象的底层const,函数指针和成员函数指针不可用于 const_cast

const A *pca1 = new A;                          //A是一个类
A *pa2 = const_cast(pca1);                  //常量对象转换为非常量对象 

const A &a1 = a0;
A a2 = const_cast(a1);                     //常量引用转为非常量引用 

//下面两情况是未定义的情况
const char *pc;
char *p = const_cast(pc);               //正确,但是通过p写值是未定义的行为,因为pc没有值


const int j = 3; // 声明 j 为 const
int* pj = const_cast(&j);
// *pj = 4;      // 未定义行为

4.5 dynamic_pointer_cast、lexical_cast、duration_cast

以后有空再学了,目前使用不到

  1. dynamic_pointer_cast: Dynamic cast of shared_ptr. Returns a copy of sp of the proper type with its stored pointer casted dynamically from U* to T*.
  2. boost::lexical_cast: 为数值之间的转换(conversion)提供了一揽子方案,比如:将一个字符串"123"转换成整数123,代码如下:
  3. duration_cast()函数提供了在不同的时间单位之间进行转换的功能。

你可能感兴趣的:(c++)