每天进步一点点,时刻保持学习的状态
目录
1:普通函数重载
将一个相同名字但是不同类型的函数重复重复调用多次,来处理不同类型的数
据。
2:成员函数重载
用对象 分别访问并调用带参数和不带参数的 成员函数,编译器将根据参数的不同而自动调用不同的函数
3:函数参数带默认值
在定义某个函数时将它的参数也初始化,那么这个或这些参数就是该函数默认参数,又称缺省参数。例如:
声明一个带默认值的函数 fun
void fun(int x=0,int y=0); //将两个参数都初始化为 0
4:构造函数重载
创建对象是,根据传入构造函数的参数个数决定执行某个构造函数
5:复制构造函数
复制构造函数可以复制一个对象,如:
A();
A(A&);
第 1 行声明了一个构造函数,第 2 行则声明了一个复制构造函数,我们看到它有一个属于类 A 的引用,那么这个复制构造函数就可以通过该引用来访问它的对象,然后复制该对象的成员变量。如
A(A &one);
A 类的复制构造函数针对类 A 对象 one 以别名的方式进行访问。由于引用只能被初始化而不能被赋值,因此把这个引用声明为常量引用是个非常好的主意,这样,构造函数就不必改变传递进来的对象。每个类都有一个默认复制构造函数,它使用一个实例来演示一个默认复制构造函数的使用情况。
6:构造函数和 new 运算符
(1) 栈由系统自动分配内存,堆要程序员进行申请。
(2) 栈中空间比较小,只有 2MB,堆的上限是由系统中有效的虚拟内存来定的,因此获得的空间比较大
A *a = new A(4,2);
当使用 new 运算符建立一个类对象时,比如说类 A 的对象,new 首先分配足以保存该类的一个对象所需要的内存,然后自动调用构造函数来初始化这块内存,再返回这个对象的地址。对于表达式:new A; 调用不带参数的构造函数,而对于表达式:new A(2,5);则是调用带参数的构造函数
7:默认构造函数
当我们没有给一个类定义构造函数的情况下,C++编译器将为我们自动建立一个不带参
数的构造函数,这个不带参数的构造函数就是默认构造函数,如:
A::A(){}
8:析构函数和 delete 运算符
与 new 和构造函数相同,delete 运算符与析构函数搭配使用,当使用该运算符删除某个
对象时,它会自动调用析构造函数来释放这个对象所占用的内存空间
int main()
{
A *p=new A;
delete p;
p = NULL;
return 0;
}
与构造函数一样,假如我们不指定自己的析构函数,那么编译器将为我们创建一个默认
析构函数,它的形式如下:~A(){};
它的函数体是空的,所以该析构函数执行时不会输出任何信息。
9:浅层复制构造函数
所有复制构造函数均有一个参数,即对同一个类的对象的引用
由于需要复制的对象一般不会更改,因此通过将引用定义为常量引用,这样构造函数就
不用改变传递进来的对象,如:
A(const A&a);
这样该函数就可根据这个对象 a 来生成一个副本。这个 a 只是个形式参数,它代表进来
对象。
编译器提供了默认构造函数的析构函数,同样也提供了复制构造函数,编译器提供的默
认复制构造函数只是把传递进来的对象的每个成员变量复制到新对象成员变量中去。然后两
个对象中的变量均指向存放成员变量的那块内存区域。假如该变量不是指针变量,一般不会
立即出错,假如该变量是指针变量。当这两个对象中任何一个超出作用域时,都会出现致命错误。比如将对象 a 删除,那么析构函数会自动释放堆中存放 6 的那块内存空间,而对象 b 的指针变量 x 仍然指向该空间,由于该空间已经不存在,那么对象 b 指针变量 x 现在就成了一个迷途指针,该程序处于崩溃的边缘。
10:深层复制构造函数
为了解决浅层复制导致的迷途指针问题,我们必须创建自己的复制构造函数,并且在函
数中为我们成员分配内存,这样,在分配完内存后,旧对象的成员变量就可以复制到新的内
存区域中,两个对象的成员变量都各自拥有自己的内存区域,一个对象在析构后不会影响到
另一个,我们把这种复制方式叫做深层复制。
#include<iostream>
using namespace std;
class A
{
public:
A(){x = new int; *x = 10;}
~A(){delete x;x = NULL;}
A(const A &a)
{
cout << "复制构造函数被执行\n" << endl;
x = new int;
*x = *(a.x);
}
void print()const{cout << *x << endl;}
void set(int i){*x = i;}
private:
int *x;
};
int main()
{
A *a = new A();
cout << "a = "<<a->print(); cout << endl;
A b = (*a);
a->set(22);
cout << "b = "<< b.print(); cout << endl;
b.set(50);
cout << "a = "<< a->print();cout << endl;
delete a;
return 0;
}
输出:
a = 10
复制构造函数被执行
b = 10
a = 22
我们在默认复制函数中添加了一行:
x =new int;
在复制构造对象的同时创建一块新空间,并且成员指针变量 x 来保存该空间地址,这样
旧的成员指针和新的成员指针分别指向不同的内存区域,也就不会出现删除一个对象后导致
另一个对象成员指针成为迷途指针的情况。
*x = *(a.x);
这样的作用是将旧对象的成员指针 x 指向的空间处的数据赋给新对象的成员指针 x 指向
的空间,即两个对象的成员指针分别指向不同的内存空间。我们必须复制指针指向的空间处
的数据而不是仅仅复制指针本身