C++day1-day2

1.day1

1.1重载

出现在相同作用域中的函数,有相同的函数名,而形参表不同,称为重载函数。编译器根据所传递的实参类型来判断调用哪个函数。
eg:
int max(int a, int b);
double max(double a , double b);
char* max(char* a, char* b);
函数不能仅仅基于不同的返回值类型而实现重载。

1.2引用

1.2.1引用的定义

形如
int a = 10;
int &b = a;
b称为a的引用,b是a的别名。引用变量b与变量a绑定在一起,也叫相关联。
&表示引用声明符,不是取地址符。b和a占同一内存存储单元。
ps:
1.在定义一个引用时,必须同时初始化。
2.当引用初始化后,只要该引用存在,它就与初始化时指向的对象相关联,不能将引用关联到其它对象。
3.引用不是独立的数据类型,是复合类型,必须使其代表某一类型的对象。
4.可以定义数组引用。

1.2.2引用和指针的区别:

1.从内存分配上看:指针是一个实体,而引用仅是个别名。程序为指针变量分配内存区域,而引用不需要分配内存区域,它与它所绑定的对象占同一内存存储单元。
2.“sizeof 引用”得到的是引用所绑定的对象的大小,而“sizeof 指针”得到的是指针本身的大小;
3.引用使用时无需解引用(*),指针需要解引用;
4.引用只能在定义时被初始化,之后就不能改变它和它所绑定的对象之间的联系,指针可改变指向。

1.2.3使用引用形参的情况:

以下两种情况优先选择引用形参:
1.需要在函数中改变实参的值时。
2.大型的对象(如类对象)作为实参传递时,此时复制对象所需要的时间和空间的代价都较大。
以下一种情况必须使用引用形参:
1.对象无法进行复制时。(比如IO流对象)

1.2.4引用作为函数返回值需要注意的问题:

1.函数返回引用类型时,不会复制返回值,返回的是对象本身。
2.不要返回绑定局部对象的引用,函数调用结束,局部对象被释放,返回的引用就会指向不确定的内存。
3.不要返回指向栈内存的指针,因为函数调用结束,局部对象被释放,返回的指针变成了指向不再存在对象的悬垂指针。

1.3面向对象编程

1.3.1面向过程编程和面向对象编程的区别

面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
(以数据为中心)

面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题的步骤中的行为。
(以行为为中心)

1.3.2面向对象的三个基本特征

1.封装性:private, protected, public
2. 继承性
3. 多态性

1.4类的定义

1.4.1类的访问权限

private: 私有成员
只能被本类中的成员函数引用,类外不能调用。
public: 公有成员
可以被本类中的成员函数引用,也可以在类外被引用。

1.4.2类对象

类的定义不会引起数据的内存分配。
只有定义该类的对象时才会给这个对象分配存储空间。
类对象所占的存储空间既它的数据成员所占的空间。
每个类对象都有自己的数据成员。

定义类类型的对象的方式:
类名 对象名
student s1;

1.4.3类的作用域

1.每个类都定义了自己的作用域和类型,在类的定义体内声明类成员,将成员名引入类的作用域。
2.在类的作用域外,只能通过对象或者指针分别使用成员访问操作符. 或者->来访问。
3.在类外定义成员函数要使用类名加作用域限定符::
4.成员函数的形参表和函数体处于类的作用域中。
5.成员函数的返回值类型不处于类的作用域中,如果要使用在类中定义的类型则必须在返回值前面加类名和作用域限定符。

1.4.4类和结构体的区别

在C++中类和结构体有两点不同:
1.class默认的成员属性是private ,struct默认的成员属性是public。
2.在继承层面:class默认的继承方式是私有继承,而struct默认的继承方式是公有继承。

1.5内联函数

1.5.1引入内联函数的意义

在调用内联函数时,并不真正执行函数的调用过程,只是把函数的代码嵌入到程序的调用点,减少了函数调用的开销。

1.5.2内联函数总结

1.内联函数使用inline关键字定义。
2.关键字和函数定义必须结合在一起,否则编译器将它作为普通函数对待。
3.在类内部定义的成员函数自动视为内联函数,不需要加关键字inline。
4.内联机制适用于优化小的,只有几行的,且频繁被调用的函数(如获取或者设置类数据成员的函数)。
5.类的普通成员函数一般在源文件内定义,类的内联成员函数最好在头文件中定义。

1.6this指针

每个成员函数都有一个隐含的形参this。
this是一个指针,指向调用成员函数的类对象。
在调用成员函数时,this被初始化为调用函数的类对象的地址。

1.6.1this指针的使用

1.在成员函数中,不需要显式的使用this指针来访问对象的成员,默认其成员为通过指针this实现的引用。

int  student::get_age( )
{
	return age;   //==>return this.age;
}

2.当需要将一个类对象作为整体引用时,需要显式的使用this。

student& student::get_object( )
{
	return *this;
}

2.day2

2.1构造函数

2.1.1知识要点

1.构造函数的函数名必须与类名相同。
2.构造函数可以没有形参,也可以定义多个形参。即构造函数可以被重载,实参的类型和个数决定调用哪个构造函数。
3.构造函数不能指定返回类型,不返回任何值。即它既不属于返回值函数也不属于void函数。
4.构造函数是一种特殊的成员函数,构造函数不需要使用者主动调用,而是建立对象时自动执行。

2.1.2构造函数的初始化列表

2.1.2.1初始化列表的形式
class Student
{
	 int m_age;
	string m_name;
	char m_sex;
};

Student::Student(int age, string name, char sex)
: m_age(age), m_name(name), m_sex(sex) { }

2.1.2.2初始化和赋值的区别

初始化是指创建对象的同时给它赋初值。
赋值是擦除对象的当前值并用新值代替。

2.1.2.3初始化列表与函数体内赋值的区别

使用初始化列表初始化数据成员与在构造函数体中赋值的效果是相同的,不同之处在于:
1.初始化列表是执行初始化过程,在创建数据成员的同时给它们赋初值。
2.在构造函数体中赋值是执行赋值过程,数据成员在执行函数体之前就已经创建,有一个值,在函数体里重新赋给数据成员新的值。

2.1.2.4初始化列表知识要点

1.const成员,引用类型成员要求在创建时就必须赋初值,因此只能使用初始化列表对其进行初始化。
2.初始化列表仅指定用于初始化成员的值,并不指定这些成员初始化执行的次序。成员被初始化的次序就是类中定义成员的次序。
3.初始化式,即括号里的内容可以是变量,是常量也可以是表达式。

2.1.3默认构造函数

1.如果类中没有定义任何一个构造函数,编译器会自动合成一个默认构造函数。
2.若定义了不带参数或各参数均有默认值的构造函数,C++编译器都认为其是默认的构造函数。
3.一个类只能有一个默认构造函数。
4.一个类通常应该显式的定义一个默认构造函数

2.1.4复制构造函数

2.1.4.1复制构造函数的定义

复制构造函数(拷贝构造函数)是一种特殊的构造函数,具有单个形参,该形参是对该类类型的引用。
把新创建的类对象初始化为形参类对象的副本。

2.1.4.2何时调用复制构造函数

复制构造函数也是编译系统自动调用的,下列情况会调用复制构造函数:
1.根据另一个同类型的对象初始化一个对象
类名 对象2(对象1);
类名 对象2=对象1;
Student stud2(stud1); 直接初始化
Student stud2 = stud1; 复制初始化
2.当类对象作为实参时,传递给函数的非引用类型形参时。
3.返回值为非引用类类型时。

2.1.4.3合成的的默认复制构造函数

如果类中没有显式的定义复制构造函数,编译器会合成一个默认的复制构造函数。
这个默认的复制构造函数执行的行为是,逐个成员初始化,将新对象初始化为原对象的副本。

class Student{
	 int m_age;
	string m_name;
	char m_sex;
};

Student(const Student &orig)
:m_age(orig.m_age),m_name(orig.m_name),m_sex(orig.m_sex) {}

2.1.4.4复制构造函数知识要点

1.当类中有成员是指针变量时或者在类中有动态分配内存的情况发生,此时对于复制对象时发生的情况要加以控制,要求必须显式的定义自己的复制构造函数。否则在复制过程中容易产生错误。
2.最好在类中显式的定义复制构造函数,而不是使用默认的复制构造函数。

2.2析构函数

2.2.1 析构函数的定义

同构造函数一样,析构函数也是类的特殊成员函数,在撤消类对象时会自动调用。

2.2.2合成的析构函数

不管是否显式的定义了析构函数,编译器都会自动的合成一个析构函数。
合成的析构函数按照数据成员创建时相反的顺序来释放这些成员。

2.2.3析构函数知识要点

1.析构函数的名字是“~”加上类的名字(中间没有空格)。
2.析构函数在类对象销毁时自动执行。
3.与构造函数一样,析构函数也没有任何类型,即不属于返回值函数也不属于void函数。
4.与构造函数不同,析构函数没有参数。
5.一个类只能有一个自定义的析构函数,析构函数不能重载。
6.不管是否显式的定义了析构函数,编译器都会自动的合成一个析构函数。

2.3对象的动态建立和释放

2.3.1new操作符

返回指向新创建对象的指针,可以通过指针来访问该对象

int *pi = new int;
string *ps1 = new string;
string *ps2 = new string(“hello world”);
string *ps3 = new string[3];

2.3.2delete操作符

释放动态创建的对象
如果是单个对象空间,使用下列方式:
delete pt;
如果是数组空间,使用下列方式:
delete [ ] pt2;
表示把整个数组的空间都释放,而不是数组的某个元素。

ps
1.在delete之后,要设置指针的值为NULL,避免野指针的出现。
2.C++允许删除值为NULL的指针。
int * p = NULL;
delete p;
3.需要注意动态内存相关的:内存泄露,越界,重复释放等问题。

2.3.3new delete 与 malloc free 的区别

1.用malloc函数需要指定内存分配的字节数,不能初始化对象。
2.new 会自动调用类对象的构造函数,对类对象进行初始化。
3.new是C++运算符,返回指向创建对象的指针,malloc是C标准库函数,返回void*。
4.malloc失败会返回NULL,new失败会抛出异常,程序自动终止。
5.delete 会自动调用类对象的析构函数,free不会调用类对象的析构函数。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值