初步知识

1.重载和重写

  • 重载: 在一个类中存在多个同名的函数,实现不同的功能,但是同名函数之间要么是函数的参数个数不同,要什么是函数的参数的类型不同.
  • 重写: 在C++中,它的出现,有两个前提,就是一:说存在继承的关系,通过继承子类有机会拥有父类的函数,二:该函数是virtual函数,子类根据自己的需求,改写父类的函数(不改变函数的名字,入参的个数,类型),这种现象叫做重写.

2.函数模板

  • 函数模板的出现,也是为了可以实现类似函数重载的作用,即,同名函数可以做不同的事情
    声明自己函数模板
1
2
1. template <typename M,typename T> typenameclass 关键字等效
2. 入参的个数自定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

template <class M,class T>
//和普通函数写法一样,就是把原来写死的类型,改成泛型
T myMax(T a,M b,T c){
if(b>a)
a=b;
if(c>a)
a=c;
return a;
}
int main()
{
//使用函数模板,入参的类型,个数要和模板相同,否则匹配不到,报错;
cout<<myMax(1.0,4,6.6);
return 0;
}

3.带默认参数函数

  • 带默认参数,顾名思义,就是函数在入参,在函数声明时就被初始化.

假如函数有多个参数,如下:

1
2
3
4
fun1(int a,int b,int c=1){}
fun2(int a,int b=1,int c){}//错误
fun3(int a=1,int b,int c){}//错误
//一句话,拥有默认参数函数,排在最后
  • 先声明该函数有默认参数,再使用

  • 一个函数不能既带有默认参数,有进行了重载,否则出现二义性,报错

4.内置函数

  • 作用: 有些函数会被频繁的调用,为了提高效率,C++提供的处理内置函数(内联函数) ,同样类也可以有自己的内置成员函数函数是否内置,都不占对象的存储空间

  • 使用: 在函数返回值类型加上关键字: inline

1
inline int fun (){ ... }

理解: 有時候为了让程序看起来比较清晰,一般函数的实现都在写在主函数的外部,在主函数中只是对定义好的函数进行使用, 也就是说,在主函数中只有函数头,而没有函数体.在这种情况下,相当于告诉编译器,我有这个合法的函数,但是这个函数究竟 是有什么作用我并没有告诉它,需要他根据地址,自己去找.而内置函数就是在编译期就在把代码嵌入到主函数中,以后再调用,就不用再去查找了…

5.动态分配/撤销内存的运算符 new 和 delete

语法:

1
2
3
4
5
6
7
8
9
10
11
12

new 类型 [初值] //会返回一个指向该 类型的 指针
delete [] 指针变量

//开辟
new int;//动态开辟一个存放int类型的空间,返回指向该空间的指针
new int(10);//动态开辟一个存放int类型的空间,赋初值10,返回指向该空间的指针
char* pt = new char[10]//动态开辟一个存放字符数组的空间,返回指向该空间的指针
float* p = new float(1.11);
//释放
delete p;
delete[] pt;//[]表示是对数组空间的操作

类与对象

1. 数据成员的初始化

  • 使用有参的构造函数,在函数体中对数据成员进行初始化
  • 使用有参的构造函数,配合参数初始化表对数据成员进行初始化
  • set方法

2. 参数初始化表

  • 注意点: 不能对数组进行初始化

3. 关于构造函数

  1. 何时调用: 每当创建对象的时候,会根据传递进去的参数的个数,类型.去类中匹配相应的构造函数
  2. 返回值: 无
  3. 是否可被用户调用: 用户无权调用,系统自动执行
  4. 可以用一个类的对象初始化本类的另一个对象
  5. 构造函数体中可以包含与初始化无关的语句,但是不提倡
  6. 可带默认参数
  7. 可重载

4. 关于析构函数

  • 对象的生命周期结束时,进行收尾工作

5. 构造函数和析构函数的执行顺序

  • 按对象的声明顺序,依次执行对象的构造函数,最后创建的对象的析构函数最先执行

6. 对象数组

  • 顾名思义,数组里面是承载的是一个一个的对象
1
类型 自定义名 [索引]{ 构造函数(入参1,...),构造函数(入参1...)......}

7. 对象指针与引用

  • 其实无论是对象指针还是指向对象数据成员的指针,和c语言的指针理解起来是一样的…

  • 对象指针: 取当前对象的地址,赋值给和此对象相同类型的指针就好了

  • 引用: 也称他是取别名.
  • 相同点: 他们实现的功能是相同的…
  • 不同点: 对象指针返回的是指向那个对象的指针,虽然通过指针可以对该对象进行操作,但是这个指针终究不是该对象 引用的话,返回我们的就是这个对象,只不过就是换了个名字,取了个小名
1
2
3
4
5
6
7
class Time{};
//对象指针:
Time t;
Time* p = &t;
//引用
Time t;
Time& p1 = t;

8. 指针

1.指向普通函数的指针

1
2
3
4
//类型名(* 指针变量名)(参数表)
void (*p)() // p是指向返回值为void 类型的,且函数无入参的函数的指针
p=fun;
(*p)(); //调用

2. 指向对象的成员函数的指针

1
2
3
4
//数据类型名(类名:: *指针名)(参数列表)  ////类名::不能省略,这两种函数区别
//声明
void (Time:: *p)();
p=&Time::get(); //后面的&不建议省略

3. this指针

  • 每个对象中的数据成员都占有不同的存储空间.假设我们如果创建了同一个类的多个对象,那么,当不同的对象调用同一个函数的目标代码时,它在这个目标函数中所使用的数据成员是不会出现A对象使用B对象的数据成员的现象的,原因就是,存在隐式的this指针

  • this指针是指向本类对象的指针,当前用到那个对象,this就指向谁,他的值就是当前被调用的成员函数所在的对象的起始地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 //场景1;
class Time{
private:
int H;
int M;
int S;
public:
Time(int H, int M , int S){//入参名和数据成员名相同...用this指针区别
this->H=H;
this->M=M;
this->S=S;
}

};

//场景2:
//在定义一个类的时候,
class Time{
private:
int H;
int M;
int S;
public:
Time(int H, int M , int S){//入参名和数据成员名相同...用this指针区别
this->H=H;
this->M=M;
this->S=S;
}

void display(){
cout<<H<<M<<S<<endl; //this指针省写;
cout<<this->H<<this->M<<this->S<<endl; //写全this指针
}

};

4.指向对象的常指针

1
2
3
4
5
6
// 类名* const 指针变量名
Time t(1,2,3);

Time* const p;
p=&t; //p是一个常指针,对他自己而言,它始终如一的指向t对象,
//而对t对象来说,它的值是可以后续通过set方法改变的

5. 指向常对象的指针变量

1
2
3
4
5
6
7
8

//const 类型名* 指针变量名
const Time t(1,2,3); //t是Time类型的变量,而且被const修饰,说明它是个常对象
//即,对象里面的数据成员不可改变
const Time* p;

p=&t; //对于p而言,他指向Time类型的t,但是它没有被const修饰,因此,它可以重新指向别的对象,
//但是不能通过p去改变 t的值