第2讲 引用和指针的区别

---------------------第2讲 引用和指针的区别-----------------------
1、指针:指针是一个实体,需要分配内存空间;定义的时候可以初始化也可以不初始化;指向的空间可以变化;
(1) .h文件中

QFile* my_file;
RadarDataProcessingObject* radar_data_processing_object;

(2).cpp文件中

my_file = nullptr;
radar_data_processing_object = new RadarDataProcessingObject;

2、引用:引用只是一个变量的别名,不需要分配内存空间,但是在定义的时候必须初始化,并且不能够改变;

hhh::hhhhh(const int& new_track_id)    // 参数是引用,其优点是避免了拷贝,节约了系统的资源。

3、指针和引用的自增运算结果不一样(指针是指向下一个空间,引用是引用的变量值加一)

4、sizeof引用得到的是所指向的变量的大小,而sizeof指针得到的是指针本身的大小。

5、作为参数时也不同,传指针的实质是传值,传递的值是指针的地址;
传引用的实质是传地址,传递的是变量的地址;
因此,被调函数对形参的任何操作都是作为局部变量进行的,不会影响主调函数的实参变量的值(即:形参指针变了,实参指针不会变,因为形参中存放的是实参指针的地址),但是,引用就不一样了,引用参数传递时,被调函数的形参存放的是实参变量的地址,被调函数对形参的任何操作都会影响主调函数的实参变量。

6、引用访问一个变量是直接访问,无需解引用(*),而指针访问一个变量是间接访问,需要解引用;

7、引用的底层是通过指针实现的。

-------------------第3讲 面向对象编程的特点----------------------
面向对象编程的三大特性:封装、继承、多态;
1)封装:把自己的属性和方法分装在一起,把对象的属性私有化,同时提供可以被外界访问这些属性的方法;封装的意义是隐藏了代码的具体实现方法,实现的改变或升级对于使用方来说是无感知的,提高了程序的可维护性。

2)继承:继承是指子类对父类的继承,子类把父类的属性和方法继承过来,同时可以添加自己新的属性或新的方法;继承是代码重用的基础机制;

3)多态:没有继承就没有多态,继承是多态的前提。由继承而产生的不同的子类,其对象对同一消息会做出不同的响应。在父类的函数前加上 virtual 关键字,在子类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是子类,就调用子类的函数;如果对象类型是父类,就调用父类的函数。
C++支持两种多态方式:编译时多态性、运行时多态性。
a.编译时多态性:通过重载、模板实现;
b.运行时多态性:通过覆盖、虚函数实现。

重载函数:是指函数名字相同,但是函数的参数类型或者参数个数并不相同

函数模板:如下

template<typename T>
T funcAdd(T a, T b)
{
   T addhe = a + b;
   return addhe;
}

int he = funcAdd(11,12);   // T 代表int,返回结果为23

覆盖(函数遮蔽):只要父类和子类中有重名函数,子类的函数就会遮蔽掉父类中的同名函数,这里不管函数的返回值或参数相不相同。

虚函数:虚函数的提出是为了解决只定义一个对象指针,就可以调用父类及各个子类的同名成员函数。虚函数在声明的时候用virtual关键字开头。注:父类和子类中的同名函数(虚函数)都要用virtual开头,且在子类的虚函数末尾加override关键字,以保证父类子类中函数同名同参,从而构成虚函数。

// 父类 human.h
#idndef __HUMAN__
#define __HUMAN__
#include<iostream>
class Human
{
  public:
     Human();
     virtual void eat(); 
};
#endif
// 父类 human.cpp
#include<human.h>
Human::Human()
{
}
void Human::eat()
{
   std::cout <<"人类吃各种粮食"<<std::endle;
}
// 子类 men.h
#idndef __MEN__
#define __MEN__
#include<iostream>
#include<human.h>
class Men:public Human
{
  public:
     Men();
     virtual void eat() override; 
};
#endif
// 子类 men.cpp
#include<men.h>
Men::Men()
{
}
void Men::eat()
{
   std::cout <<"男人吃各种粮食"<<std::endle;
}
// 子类 women.h
#idndef __WOMEN__
#define __WOMEN__
#include<iostream>
#include<human.h>
class Women:public Human
{
  public:
     Women();
     virtual void eat() override; 
};
#endif
// 子类 woman.cpp
#include<woman.h>
Women::Women()
{
}
void Women::eat()
{
   std::cout <<"女人吃各种粮食"<<std::endle;
}

在main函数中加入如下代码

Human* phuman;
phuman = new Human;
phuman->eat();   // 父类指针指向父类(本身)对象
delete phuman;

phuman = new Men;
phuman->eat();   // 父类指针指向子类Men对象
delete phuman;

phuman = new Women;
phuman->eat();   // 父类指针指向子类Women对象
phuman->Human::eat(); // 调用父类eat()函数(重点)
delete phuman;

---------------第4讲 构造函数与析构函数的调用顺序-------------
(1)构造函数调用顺序:
基类构造函数、对象成员构造函数、派生类本身构造函数
注:当某个类继承多个类时,
(2)析构函数调用顺序:
派生类本身的构造函数、对象成员函数析构函数、基类析构函数

-------------第5讲 动态编译与静态编译------------------------
1)静态编译:编译器在编译可执行文件时,把需要用到的对应动态链接库中的部分提取出来,连接到可执行文件中去,使可执行文件在运行时不需要依赖于动态链接库。即,静态编译是指把需要用到的动态链接库提取出来,放到可执行文件中去,使可执行文件在运行的时候不需要依赖动态链接库;
2)**动态编译是指没有把动态链接库放到可执行文件中去,因此需要附带一个动态链接库,在执行时,调用对应的动态链接库。**优点:缩小了可执行文件的体积,另一方面是加快了编译速度,节省了系统资源。缺点:对于没有安装对应的运行库时,可执行文件无法运行。

---------------第6讲 static的用法和作用---------------------
1.函数内部在定义一个局部变量时,在前面使用static关键字,则该变量会保存在静态存储区,在编译的时候被初始化,如果不给初始值,他的值会被初始化为0,并且,下次调用该函数时,该变量保持上次离开函数时的值。例如

void func()
{
// 用关键字 static 定义的局部变量保存在静态存储区,函数调用完,该局部变量内存不会回收,下次调用该函数时,该变量保持上次离开的值
   static int tmpvalue = 1;  
}

2.在定义全局变量时,前面使用static关键字,那么该全局变量只能在本文件中使用,无法在其他文件中被引用(使用)。例如:

static int g_a = 6; // 用关键字 static 定义的全局变量只能在本文件中使用
  1. 函数定义之前增加static关键字,那么该函数只能在本源程序文件中调用,无法在其他源程序文件中调用,例如:
//函数只能在本源程序文件中调用,无法在其他源程序文件中调用
static void g_func(){...} 

4.static关键字在中的能力

#idndef __HUMAN__
#define __HUMAN__
#include<iostream>
class Human
{
  public:
     Human();
     ~Human();
  public:
  static int mystatic;                       // 声明静态成员变量但没有定义
  static void mystaticfunc(innt testvalue);  // 声明静态成员函数
};
#endif

----------静态成员变量-----------

static int mystatic;                       // 声明静态成员变量但没有定义

静态成员变量与普通成员变量不同,普通成员变量在定义一个类对象时,就已经分配内存了,但是static int mystatic这段代码只是对静态成员变量的声明,并没有分配内存,为了能够使用静态成员变量,就必须给静态成员变量分配内存,分配内存的方法如下:
在.cpp文件的最上面添加如下代码:

//可以不给初值,系统默认初值为0,同时,这里定义时无需用static关键字
int Human::mystatic = 5; 

对类中静态成员变量的访问方法有两种,如下:
(1)类名::成员变量名

cout<<Human::mystatic<<endl;

(2)对象名.成员变量名

Human g_human;
g_human.mystatic = 12;  // 用对象名访问成员变量

----------静态成员函数-----------

static void mystaticfunc(innt testvalue);  // 声明静态成员函数

用静态函数的需要注意的地方;
a) 与静态成员变量类似,都需要声明和实现
b) 在定义的时候不需要加static关键字

void Human::mystaticfunc(int testvalue)
{
   mystatic = testvalue;
}

c) 在静态函数中不允许出现静态变量
d) 静态函数和静态变量都可以通过类名或对象名来调用

Human::mystaticfunc(1288);    // 通过类名调用
Human g_human;
g_human.mystaticfunc(1288);   // 通过对象名来调用

--------------第7讲 动态存储区和静态存储区----------------------
在这里插入图片描述
(1)动态存储区(堆+栈) 指在程序运行期间根据需要进行动态的分配存储空间的方式。
a) 栈区:由编译器自动分配释放,主要用于存放函数的参数、局部变量等值;
b) 堆区:由程序员分配释放(new/delete),堆允许程序在运行时动态地申请某个大小的内存。注:若程序不释放内存,会导致内存泄漏。
(2)静态存储区 是指在程序编译期间分配固定的存储空间的方式。
a) 数据段
i)只读数据段:用于存放const修饰的变量以及程序中使用的文字常量
ii)已初始化的读写数据段:用于存放已经初始化的全局变量,已经初始化的静态局部变量(static修饰的已经初始化的变量);
iii) 未初始化段:未初始化数据是在程序中声明,但是没有初始化的变量,这些变量在程序运行之前不需要占用存储器的空间。与读写数据段类似,它也属于静态数据区。但是该段中数据没有经过初始化。未初始化数据段只有在运行的初始化阶段才会产生,因此它的大小不会影响目标文件的大小。在程序中一般是没有初始化的全局变量和没有初始化的静态局部变量。
b) 程序代码区:存放函数体的二进制代码。所有的语句编译后会生成CPU指令存储在代码区.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值