1.重载函数
// 函数重载:函数名相同,可以有不同的定义 实现形式不同
void swap_int(int &a, int &b)
{
int tmp = a;
a = b;
b = tmp;
}
void swap_double(double &a, double &b)
{
double tmp = a;
a = b;
b = tmp;
}
void swap_char(char &a, char &b)
{
char tmp = a;
a = b;
b = tmp;
}
// 函数名相同,形参类型不同,可以构成函数重载
// C++编译器对函数的处理:编译的时候将参数类型加入到函数名中形成新的函数名
// C++编译器对函数的处理:编译的时候将参数类型加入到函数名中形成新的函数名
// 函数重载的规则:
// 1、参数类型不同
// 2、参数个数不同
// 3、参数的顺序不同
// 1、参数类型不同
// 2、参数个数不同
// 3、参数的顺序不同
int add(int a, int b) // addii
{
return a + b;
}
int add(int a, int b, int c) // addiii
{
return a + b + c;
}
{
return a + b;
}
int add(int a, int b, int c) // addiii
{
return a + b + c;
}
// 注意事项:函数的返回值不能作为重载的条件
函数重载和函数默认参数 使用的时候需要注意
2.类
// 封装:
// 1、将 数据(变量==属性) 和 操作数据的方法(函数) 放到一块
// 2、对 内部成员提供访问控制 达到信息隐藏的目的
// 1、将 数据(变量==属性) 和 操作数据的方法(函数) 放到一块
// 2、对 内部成员提供访问控制 达到信息隐藏的目的
// 类 === 类似高级的结构体
// class 用来定义类
// 访问控制:
// public : 公有成员 在类的内部和外部都可以使用
// private : 私有属性 在类的内部可用, 外部不可用
// protected: 保护属性 在类的内部可用, 外部不可用
// 访问控制:
// public : 公有成员 在类的内部和外部都可以使用
// private : 私有属性 在类的内部可用, 外部不可用
// protected: 保护属性 在类的内部可用, 外部不可用
class Student
{
public:
// 类的内部成员函数
void setID(int id)
{
_id = id;
}
void setName(char *name)
{
_name = name;
}
void show()
{
printf ("id = %d, name = %s\n", _id, _name);
}
char *getName()
{
return _name;
}
{
public:
// 类的内部成员函数
void setID(int id)
{
_id = id;
}
void setName(char *name)
{
_name = name;
}
void show()
{
printf ("id = %d, name = %s\n", _id, _name);
}
char *getName()
{
return _name;
}
private:
int _id; // 成员变量 属性
char *_name; // 成员变量 属性
};
int _id; // 成员变量 属性
char *_name; // 成员变量 属性
};
// 定义一个类的变量 我们将这个变量叫做 该类的一个 对象
Student s, s1, s2;
Student s, s1, s2;
3.结构和类的区别
// 结构默认的成员属性是 公有的
struct A
{
int ma;
};
struct A
{
int ma;
};
// 类默认的成员属性是 私有的
class B
{
int mb;
};
class B
{
int mb;
};
4.类的使用规范
5.构造函数和析构函数
// 构造函数:在定义对象的时候对 对象进行初始化的函数
// 1、函数名和类名相同
// 2、构造函数没有返回值
// 3、构造是不需要手动调用的,在创建对象的时候编译器自己调用
// 4、构造函数可以被重载
// 1、函数名和类名相同
// 2、构造函数没有返回值
// 3、构造是不需要手动调用的,在创建对象的时候编译器自己调用
// 4、构造函数可以被重载
// 拷贝构造函数:用另一个对象 对当前对象进行初始化
// 类名(const 类名 &变量名)
// 类名(const 类名 &变量名)
// 析构函数:在对象被释放的时候编译器自动调用来释放对象资源
// 1、~类名
// 2、没有返回值
// 3、没有参数
// 4、不能被重载
// 1、~类名
// 2、没有返回值
// 3、没有参数
// 4、不能被重载
// 对象做函数参数传递的时候,会调用拷贝构造函数
// 传引用可以避免拷贝构造函数的调用
// 传引用可以避免拷贝构造函数的调用
// void func(Student s1)
void func(Student &s1)
void func(Student &s1)
// 拷贝调用:函数返回值是对象
// 1、不使用函数的返回值
// 函数返回的时候会产生一个匿名对象,用返回的对象对匿名对象进行初始化,调用拷贝构造函数
// 这个匿名对象没人用,所以立马被释放
// 1、不使用函数的返回值
// 函数返回的时候会产生一个匿名对象,用返回的对象对匿名对象进行初始化,调用拷贝构造函数
// 这个匿名对象没人用,所以立马被释放
// 2、用新对象去收返回值
// (1)、函数返回的时候会产生一个匿名对象,用返回的对象对匿名对象进行初始化,调用拷贝构造函数
// (2)、将 变量名 s1 给这个匿名对象使用,匿名对象变成了有名对象了
// (1)、函数返回的时候会产生一个匿名对象,用返回的对象对匿名对象进行初始化,调用拷贝构造函数
// (2)、将 变量名 s1 给这个匿名对象使用,匿名对象变成了有名对象了
// 3、用旧对象去接收返回值
// (1)、函数返回的时候会产生一个匿名对象,用返回的对象对匿名对象进行初始化,调用拷贝构造函数
// (2)、用匿名对象 对 s1 进行赋值!!!!!!!! 不会调用构造函数
// (3)、匿名对象 还是 一个匿名的 所以就被释放
// (1)、函数返回的时候会产生一个匿名对象,用返回的对象对匿名对象进行初始化,调用拷贝构造函数
// (2)、用匿名对象 对 s1 进行赋值!!!!!!!! 不会调用构造函数
// (3)、匿名对象 还是 一个匿名的 所以就被释放
class Student
{
};
Student s; // 调用无参构造函数
Student s1(10); // 调用构造函数 Student(int id)
Student s2(s); // 调用拷贝构造函数
Student s3 = s2; // 调用拷贝构造函数 用 s2 对 s3 进行初始化
6.浅拷贝和深拷贝
// 1、如果类中 一个构造函数都没有,则编译器会自动生成一个无参构造函数,是一个空的函数
// 2、如果类中没有析构函数,则编译器会生成一个析构函数,也是空的
// 3、如果类中没有定义 拷贝构造函数,则则编译器会生成一个拷贝构造函数,进行值的复制
// 3、如果类中没有定义 拷贝构造函数,则则编译器会生成一个拷贝构造函数,进行值的复制
// 编译器默认的拷贝构造 只能复制值,不能复制空间 =====> 浅拷贝
// 深拷贝:进行堆上空间的复制 ----> 自己写拷贝构造函数
Student(const Student &obj)
{
_id = obj._id;
// 给name分配空间
_name = (char *)malloc(sizeof(char)*20);
strcpy(_name, obj._name);
}
{
_id = obj._id;
// 给name分配空间
_name = (char *)malloc(sizeof(char)*20);
strcpy(_name, obj._name);
}