@value 静态变量_C++ Lesson 4:静态成员static 以及全局函数

103d1c706a0894e6d0fa261288642fbb.png

这一讲是直接照搬的郑莉老师的《C++程序设计》第5章和第六章。我上的课程中,老师没有提到static这个内容;但是static经常见到,但是我不明白道理具体是啥。这里刚好复习一下。

主要内容:

  • 类的静态成员
    • 静态数据成员
    • 静态函数成员
    • 通过函数指针,调用普通成员函数+静态成员函数。
  • 全局函数
    • 内联函数
  • 全局函数调用
    • 执行机制
    • 嵌套机制
    • 递归调用
  • static_cast

一、类的静态成员 static in class

  • 全局变量是实现数据共享的方法,但是和类的私有变量相矛盾。
  • 实现类的对象和对象之间的数据共享,可以使用静态成员
  • 静态成员属于类,由某个类的对象共同拥有。
  • 静态成员分为“静态数据成员”&“静态函数成员”

(1)静态数据成员

  • 类的一种数据成员(member variables),被类的所有对象分享(因此所有对象在这个数据上都一样)。只要储存一次,就能够提供给所有对象使用,从而节省空间。
  • 静态数据成员能够被类的对象or类更改,一个对象改了它,对所有对象都有效。
  • 使用:首先在类的private定义静态数据成员,static type name;然后在main函数之前,声明一下静态数据成员的初值,type class_name::name = 初值。
  • 模板
class 
  • 例子
#include

结果:

This circle is radium = 1.
This circle is radium = 2.
r1 circum = 6.28318, and area = 3.14159
r2 circum = 12.5664, and area = 12.5664
Destroy radium = 2.
Destroy radium = 1.

(2)静态函数成员[1]

  • 声明和定义与静态数据成员差不多,在返回值前面加上static关键字。
  • 成员函数一般都是public,因此通过类名限定or对象名限定来调用,非静态成员只能够通过对象名调用。
    • 也就是说,如果ClassName这个类中,定义了普通成员函数f1和静态成员函数f2,那么调用f1的只有ClassName生成的对象才行,而f2不仅能通过对象调用,还能够直接被ClassName调用(ClassName::f2()是ok的)。
  • 例子
#include 

运行结果

This is static.
This is ordinary.
This is static.
by ordinaryFunc: 1
by staticFunc: 1
by Somthing::staticFunc: 1

(3)通过函数指针调用成员函数

  • 回忆函数指针的用法:
//type1是函数的返回值的类型,没有返回值就是void;type2和type3是传参var1和var3的类型。

实际上,下面的类的各种成员函数的用法在此模板上基本一致。

  • 指向类的成员函数指针,指定类名即可(&类名::成员函数名
    • 通过指针调用普通成员函数(non-static)
      • 一定要有对象实例p1,才能够调用。
      • 没有传参的话,那么把type2 var2, type3 var3空着就好。
      • 用的时候,是“对象名.*函数指针名”。
type1
    • 调用静态成员函数,不需要实例化
      • 不用对象实例p1,直接能够调用。
      • 同时,鉴于静态函数的特殊性,指针定义的地方不用指明类名——因为静态函数是在全局可用。
      • 用的时候,直接用函数指针名,*也不用。
type1
  • 例子
#include 

运行结果

This is ordinary.
1.1
1
This is static.
2.1
1

可以看到,以上是①类②不同成员函数的函数指针③静态成员函数的函数指针的用法。如何定义函数指针+如何传参+是否有返回值+是否要用对象调用。

二、全局函数

1、定义

  • 主函数main能够调用全局子函数和类的成员函数,全局子函数之间、类函数之间、全局子函数和类的成员函数之间能够相互调用;主函数不能够被其他函数调用。
  • 先声明某个全局子函数而不用定义,然后写主函数(主函数中调用子函数),最后定义子函数。
#include

2、内联函数[2]

  • 函数调用也会降低程序效率(好吧。。)
    • 逻辑:调用函数的时候,CPU需要保存现场返回地址(一会儿得返回的地方),然后再转移到子函数的代码起始地址执行。子函数执行完毕,取出先前保存的返回地址和现场状态,在继续执行,因此,如果频繁调用,需要很多空间和时间开销(好吧,我知道我的Python代码又可以提高效率了。。)
    • 对于复杂的函数,调用函数的任务量反而比不上函数本身的运行时间;但是如果是小型函数,调用时间比运行时间还长。
  • 解决:内联函数,不是在调用时发生转移控制,而是在编译时,将函数整体嵌入在每一个调用处。当编译器编译代码的时候,所有的inline函数就直接放过来,而不是调用。缺点是:inline函数将会让编译代码变大。
  • 使用的时候,要写上inline关键字。格式:
    • inline 返回类型 成员函数名(形式参数表){函数体}
  • 注意点:
    • 内联函数不能够作为函数重载的区分标志(?谁会没事写两个重名函数。。)
    • 内联函数体内一般不能够有循环和switch语句。
    • 内联函数的定义,必须出现在第一次被调用之前,和普通函数不同。
    • 不能够进行异常接口的声明(??)。
    • 在类中定义的函数,即使不加inline,也默认为内联函数(??所以类中的函数都是超级有效的??)
  • 例子
#include

因为使用了两次,因此内联函数能够减少调用时间。以后我写python,也得加上inline。。

三、全局函数的调用

  • 函数调用的执行机制、嵌套机制、递归调用。

1、执行机制

d821eba4749f2a5ad42894de849c487c.png
资料来源:C++程序设计/郑莉,李超编著,图6-1 函数调用过程示意

例子,冒泡排序

#include

结果:

Enter the array length : 5

Enter 5 numbers in your array :
12
34
1
56
-1
This is after sort :
-1  1  12  34  56

2、嵌套调用

cdc529881cd88e599ca4acaea424e52e.png
资料来源:C++程序设计/郑莉,李超编著,图6-3 函数调用过程示意
  • 函数1调用了函数2,然后依次返回结果。

例子:

#include

这个函数反复进行了调用:CalArea调用了CalDistance,CalDistance调用了Square,Square调用了类里面的getX和getY。

3、递归调用

  • 调用一个函数的时候,直接或者间接调用函数自己(※※※)。这个思想在分治法divide and conquer算法中很重要,而分治法又是非常重要的算法,用李佳琦的话——OMG!!所有MM们、GG们看过来,赶紧学它学它学它!!!我在这一块真的学得稀烂。。递归法就好像斗转星移一样,能够以彼之道还治彼身~
    • 直接调用自己
void 
    • 间接调用自己
void 
  • 递归算法:将原问题拆解为新的规模较小的问题,解决新问题有用到了原问题的解法。应该包括两个重要的内容
    • 递归结束条件:当满足条件的时候,不需要再递归调用。
    • 递归调用语句。

例子:

#include

输出:

Enter the number : 5
The factorial of 5 is 120

四、static_casting[3]——explicit type conversion

1、type casting

C++中存在5种不同类型的casts:C-style casts,static casts,const casts,dynamic casts,reinterpret casts。后四种称为named casts。

2、C-style casts

int 

3、static_cast——将A类型转为B类型

typeA 

参考书籍:

C++程序设计/郑莉,李超编著.——北京:机械工业出版社,2012.1.

参考

  1. ^https://blog.csdn.net/Windgs_YF/article/details/99762327
  2. ^https://www.learncpp.com/cpp-tutorial/75-inline-functions/
  3. ^https://www.learncpp.com/cpp-tutorial/explicit-type-conversion-casting-and-static-cast/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值