目 录
函数的提高
函数默认参数
-
语法
返回值类型 函数名(参数 = 默认值)
-
特性
若传入参数,则优先使用传入的参数,否则使用默认参数
-
注意
如果形参列表中某个参数有默认值,则其后面的所有参数都必须要有默认值
函数占位参数(了解)
-
语法
返回值类型 函数名(数据类型)
-
特性
占位参数可以有默认值
函数重载
-
作用
函数名称相同,提高函数名的复用性
-
条件
- 函数名相同
- 函数在同一作用域下
- 函数参数的 类型不同 或 个数不同 或 顺序不同
-
注意
-
函数返回值不可以作为函数重载的条件
-
引用作为重载条件时,要注意加const和不加const的区别
-
当函数重载遇到默认参数时,要避免二义性的出现
-
类和对象
面向对象的特性
-
万事万物皆为对象,对象有其属性和行为
-
封装
-
继承
-
多态
-
封装
-
语法
- class 类名{访问权限:属性/行为};
-
意义
-
将属性和行为作为一个整体,表现生活中的事物
-
将属性和行为加以权限控制
-
-
示例1----设计一个圆类求出圆的周长和面积
#include <iostream> using namespace std; #define PI 3.14 //需求:设计一个圆类,求圆的周长和面积 //class代表设计一个类,后面紧跟着的就是类的名称 class Circle { //公共访问权限 public: //行为 //设置半径 void setRadius(int radius); //求周长 double getCircumference(void); //求面积 double getArea(void); //私有访问权限 private: //属性 //半径 int radius; }; int main() { //通过圆类实例化一个圆对象 Circle c1; //设置圆的半径 c1.setRadius(10); //求圆的周长和面积并打印 cout << "圆的周长:" << c1.getCircumference() << endl << "圆的面积:" << c1.getArea() << endl; return 0; } //设置圆的半径 void Circle::setRadius(int radius) { this->radius = radius; } //计算圆的周长 double Circle::getCircumference(void) { return 2 * PI * this->radius; } //计算圆的面积 double Circle::getArea(void) { return PI * this->radius * this->radius; }
运行结果:
-
成员访问权限
- public(公有权限)
- 类内可以访问,类外可以访问
- protected(保护权限)
- 类内可以访问 ,类外不可以访问
- 子类可以访问
- private(私有权限)
- 类内可以访问 ,类外不可以访问
- 子类不可以访问
- 一般都把成员属性设置为私有权限,然后在公有部分提供访问接口(成员函数)
- 优点
- 可以自己控制读写权限
- 对于写,可以检测数据的有效性
- 优点
- public(公有权限)
-
示例2----设计一个立方体类求出立方体的面积和体积
#include <iostream> using namespace std; //需求:设计一个立方体类,求出立方体的面积和体积 //创建一个立方体类 class Cube { public: //公有权限 void setLength(int length); //设置长 int getLength(void); //获取长 void setWidth(int length); //设置宽 int getWidth(void); //获取宽 void setHeight(int length); //设置高 int getHeight(void); //获取高 int getArea(void); //获取面积 int getVolume(void); //获取体积 protected: //保护权限 private: //私有权限 int length; //长 int width; //宽 int height; //高 }; int main() { //实例化一个立方体对象 Cube c1; //设置立方体的长宽高 c1.setLength(20); c1.setWidth(10); c1.setHeight(30); //打印立方体的长宽高 cout << "长:" << c1.getLength() << endl << "宽:" << c1.getWidth() << endl << "高:" << c1.getHeight() << endl; //计算立方体的面积和体积并打印 cout << "面积:" << c1.getArea() << endl << "体积:" << c1.getVolume() << endl; return 0; } //设置长 void Cube::setLength(int length) { this->length = length; } //获取长 int Cube::getLength(void) { return this->length; } //设置宽 void Cube::setWidth(int width) { this->width = width; } //获取宽 int Cube::getWidth(void) { return this->width; } //设置高 void Cube::setHeight(int height) { this->height = height; } //获取高 int Cube::getHeight(void) { return this->height; } //获取面积 int Cube::getArea(void) { return (this->length*this->width + this->length*this->height + this->width*this->height) * 2; } //获取体积 int Cube::getVolume(void) { return this->length * this->width * this->height; }
运行结果:
-
类占用空间的计算
- 成员函数放在公共代码区,不占用类的空间
- 类占用的空间实际上是成员属性所占用空间之和,但是要注意内存对齐
- 特别地,对于空类,编译器会分配一个字节空间来唯一标识这个类(占位作用)
今天的C++就学到这里叭,又是学习的一天~
----2023/08/30
对象的初始化和清理
- 构造函数和析构函数
- 构造函数
- 作用
- 创建对象时为对象的成员属性赋值
- 语法
- 类名(){}
- 规则
- 函数名与类名相同
- 没有返回值,可以有参数
- 可以发生重载
- 作用
- 析构函数
- 作用
- 对象销毁前执行一些清理工作
- 语法
- ~类名(){}
- 规则
- 函数名与类名相同,但是前面要加一个~
- 没有返回值,不可以有参数
- 不可以发生重载
- 作用
- 特性
- 由编译器自动调用,不需要手动调用,且每个对象只调用一次
- 构造函数和析构函数都是必须要有的实现,如果我们不提供,编译器会自动生成,其函数内部是空实现
- 构造函数
- 构造函数的分类和调用方法
- 分类
- 按参数分类
- 有参构造
- 无参构造(不需要传递参数的构造也称默认构造)
- 按类型分类
- 普通构造
- 拷贝构造
- 按参数分类
- 调用方法
-
括号法
//括号法 Person p1; //默认构造的调用,注意:不能加(),否则编译器会认为这是一个函数的声明 Person p2(10); //有参构造的调用 Person p3(p2); //拷贝构造的调用
-
显式法
//显式法 Person p4; //默认构造的调用,注意:不能加(),否则编译器会认为这是一个函数的声明 Person p5 = Person(10); //有参构造的调用 Person p6 = Person(p5); //拷贝构造的调用 Person(10); //单独写就是匿名对象,语句结束后系统会立即回收匿名对象
- 通过匿名对象显式的告诉编译器要调用哪种构造
- 注意
- 匿名对象的语句结束后系统会立即回收匿名对象
- 不能利用拷贝构造函数初始化一个匿名对象,否则编译器会认为是对象的声明,导致变量重定义报错
-
隐式转换法
//隐式转换法 Person p7; //默认构造的调用,注意:不能加(),否则编译器会认为这是一个函数的声明 Person p8 = 10; //相当于写了 Person p8 = Person(10); //有参构造 Person p9 = p8; //拷贝构造
-
注意
- 调用默认构造函数时不要加(),否则编译器会认为这是一个函数的声明
-
- 完整示例代码
#include <iostream> using namespace std; class Person { public: //无参构造(只要不需要传递参数的构造都称为默认构造) Person() { cout << "Person 的无参构造函数调用" << endl; } //有参构造 Person(int age) { cout << "Person 的有参构造函数调用" << endl; } //拷贝构造 Person(const Person& p) //构造函数不能修改传进来的参数,必须要用引用传递,如果使用值传递会造成无限递归导致程序崩溃 { this->age = p.age; cout << "Person 的拷贝构造函数调用" << endl; } //析构 ~Person() { cout << "Person 的析构函数调用" << endl; } protected: private: int age; }; int main() { //构造函数的调用方法 //括号法(常用) Person p1; //默认构造的调用,注意:不能加(),否则编译器会认为这是一个函数的声明 Person p2(10); //有参构造的调用 Person p3(p2); //拷贝构造的调用 //显式法 Person p4; //默认构造的调用,注意:不能加(),否则编译器会认为这是一个函数的声明 Person p5 = Person(10); //有参构造的调用 Person p6 = Person(p5); //拷贝构造的调用 Person(10); //单独写就是匿名对象,语句结束后系统会立即回收匿名对象 //隐式转换法 Person p7; //默认构造的调用,注意:不能加(),否则编译器会认为这是一个函数的声明 Person p8 = 10; //相当于写了 Person p8 = Person(10); //有参构造 Person p9 = p8; //拷贝构造 return 0; }
- 分类
- 拷贝构造函数的调用时机
- 使用一个已经创建完毕的对象来初始化另一个对象
- 值传递的方式给函数参数传值
- 以值的方式返回局部对象
#include <iostream> using namespace std; class Person { public: Person() { cout << "Person 的默认构造函数调用" << endl; } Person(int age) { this->age = age; cout << "Person 的有参构造函数调用" << endl; } Person(const Person& p) { this->age = p.age; cout << "Person 的拷贝构造函数调用" << endl; } ~Person() { cout << "Person 的析构函数调用" << endl; } protected: private: int age; }; void test01(Person p) { } Person test02(void) { Person p; return p; } int main() { //拷贝构造函数的调用时机 //使用一个已经创建完毕的对象来初始化另一个对象 Person p1(20); Person p2(p1); //值传递的方式给函数参数传值 Person p3; test01(p3); //以值的方式返回局部对象 Person p4 = test02(); return 0; }
- 构造函数的调用规则
作者乏了!!!待续…
不迈出第一步,你永远不知道你能走到哪里,加油!
2023/08/31