大纲
1 内存分区模型
1.1 程序运行前
1.2 程序运行后
//在堆区开辟数据
int * func(){
int * a = new int(100); //利用new关键字,可以将数据开辟到堆区
return a;
}
int main(){
...
int * p = func();
cout << *p << endl;
cout << *p << endl;
delete p; //释放堆区数据
...
}
1.3 new操作符
//在堆区开辟数组
void func() {
int * arr = new int[10]; //10为数组元素个数
for (int i = 0; i < 10; i++) {
arr[i] = i + 100;
}
for (int i = 0; i < 10; i++) {
cout << arr[i] << endl;
}
delete[] arr;//释放堆区数组
}
int main(){
...
func();
...
}
2 引用
2.1 引用的基本使用
2.2 引用注意事项
2.3 引用的做函数参数
void swap(int &a,int &b) {
int temp = a;
a = b;
b = temp;
}
int main() {
...
int a = 1;
int b = 2;
swap(a, b);
cout << a << endl;
cout << b << endl;
...
}
2.4 引用做函数返回值
//局部变量引用不能返回,在函数调用完后,局部变量会被清除
int& ret() {
static int a = 10; //静态变量,放在全局区,在程序结束后才清除
return a;
}
int main() {
...
int &ref = ret();
cout << "ref_1=" << ref << endl;
cout << "ref_1=" << ref << endl;
ret() = 100; //函数调用可以作为左值
cout << "ref_2=" << ref << endl;
cout << "ref_2=" << ref << endl;
...
}
2.5 引用的本质
//引用的本质:指针常量
int& ref = a;
int * const ref = &a;
2.6 常量引用
const int& ref = 10;
//防止形参修改实参
void show(const int& a) {
cout << a << endl;
}
int main() {
...
int a = 1;
show(a);
...
}
3 函数提高
3.1 函数默认参数
- 如果传入数据就用传入的数据(b=20),如果没有,就用默认值(b=10);
- 默认参数必须在最后,不能在中间;
- 函数的声明和实现只能有一个设置默认参数,不能同时;
int func(int a,int b = 10){
...
}
int main{
...
func(10,20)
...
}
3.2 函数占位参数
void func(int a,int ){
...
}
int main{
...
func(10,20)
...
}
3.3 函数重载
3.3.1 函数重载概述
3.3.2 函数重载注意事项
- 引用的函数重载
void func(int a, int b){
...
}
void func(int a, int b){
...
}
int main(){
...
int a=10;
func(a);
func(10)
...
}
- 默认参数的函数重载,应该尽量避免
4 类和对象
4.1 封装
4.1.1 封装的意义一
const double PI = 3.14;
//圆类
class circle
{
//访问权限
public:
//半径
double m_r;
//获取周长
double m_perimeter() {
return 2 * PI * m_r;
}
};
int main() {
//创建对象 实例化
circle c1;
c1.m_r = 2.1;
cout << "圆的周长为:" << c1.m_perimeter() << endl;
...
}
//类中的属性与行为--成员
//属性--成员属性、成员变量
//行为--成员函数、成员方法
const int MAX = 1000;
int num = 0;//输入学生计数
class student
{
//访问权限
public:
string arr_name[MAX];
int arr_id[MAX];
//信息输入
void input() {
cout << "姓名:" << endl;
cin >> arr_name[num];
cout << "学号:" << endl;
cin >> arr_id[num];
num++;
}
//信息打印
void output() {
for (int i = 0; i < num; i++) {
cout << "姓名:" << arr_name[i] << endl;
cout << "学号:" << arr_id[i] << endl;
}
}
};
int main() {
student arr_stu;//对象
int stu_num = 3;//输入学生数
for (int i = 0; i < stu_num; i++) {
arr_stu.input();
}
arr_stu.output();
...
}
4.1.2 封装的意义二
公共权限 成员 类内可以访问 类外可以访问
保护权限 成员 类内可以访问 类外不可以访问 子类可以访问父类的保护内容
私有权限 成员 类内可以访问 类外不可以访问 子类不可以访问父类的私有内容
class student
{
//公共权限
public:
...
//保护权限
protected:
...
//私有权限
private:
...
};
4.1.3 struct与class区别
4.1.3 成员属性设置为私有
4.1.4 案例一 立方体判断
class cube {
public:
//设置属性
void set_lwh(int l,int w,int h) {
m_l = l;
m_w = w;
m_h = h;
}
//获取属性
int get_l() {
return m_l;
}
int get_w() {
return m_w;
}
int get_h() {
return m_h;
}
//获取结果
int cal_S() {
return 2 * m_l * m_w + 2 * m_l * m_h + 2 * m_h * m_w;
}
int cal_V() {
return m_l * m_w * m_h;
}
//成员判断
//只用传入一个对比的值,有一个是已知的
bool isSame1(cube &c) {
if (m_l == c.get_l() && m_h == c.get_h() && m_w == c.get_w()) {
return true;
}
return false;
}
protected:
private:
int m_l;
int m_w;
int m_h;
};
//全局判断
bool isSame2(cube &c1, cube &c2) {
if (c1.get_l() == c2.get_l() && c1.get_h() == c2.get_h() && c1.get_w() == c2.get_w()) {
return true;
}
return false;
}
int main() {
cube c1;
cube c2;
cube c3;
//设置长 宽 高
c1.set_lwh(1, 2, 3);
c2.set_lwh(1, 2, 3);
c3.set_lwh(2, 2, 3);
cout << c1.cal_S() << endl;
cout << c1.cal_V() << endl;
//成员对比
bool ret1 = c1.isSame1(c2);
bool ret3 = c1.isSame1(c3);
//全局对比
bool ret2 = isSame2(c1,c2);
bool ret4 = isSame2(c1,c3);
if (ret1 && ret2) {
cout << "1,2 一样" << endl;
}
else {
cout << "1,2 不一样" << endl;
}
if (ret3 && ret4) {
cout << "1,3 一样" << endl;
}
else {
cout << "1,3 不一样" << endl;
}
...
}
4.1.5 案例二 点圆关系判断 及 class 的头文件封装
//点类
class point {
public:
void set_xy(int x, int y) {
p_x = x;
p_y = y;
}
int get_x() {
return p_x;
}
int get_y() {
return p_y;
}
private:
//位置xy
int p_x;
int p_y;
protected:
};
//圆类
class circle {
public:
void set_r(int r) {
c_r = r;
}
void set_o(point c) {
c_o = c;
}
int get_r() {
return c_r;
}
point get_o() {
return c_o;
}
private:
//圆心xy
point c_o;
//半径
int c_r;
protected:
};
//距离比较
void c_p(circle &c, point &p) {
int distence_cp = (c.get_o().get_x() - p.get_x()) * (c.get_o().get_x() - p.get_x()) + (c.get_o().get_y() - p.get_y()) * (c.get_o().get_x() - p.get_x()) - c.get_r() * c.get_r();
if (distence_cp == 0) {
cout << "点在圆上" << endl;
}
else if (distence_cp > 0) {
cout << "点在圆外" << endl;
}
else {
cout << "点在圆内" << endl;
}
}
int main() {
//定义点和圆对象
circle c;
point c_o;
point p1;
point p2;
point p3;
//设置圆属性
c.set_r(2);
c_o.set_xy(0, 0);
c.set_o(c_o);
//设置点属性及比较
p1.set_xy(2, 0);
c_p(c, p1);
p2.set_xy(1, 0);
c_p(c, p2);
p3.set_xy(3, 0);
c_p(c, p3);
...
}
把类封装成.h文件
- point.h
#pragma once
#include<iostream>
using namespace std;
class point {
public:
void set_xy(int x, int y);
int get_x();
int get_y();
private:
//位置xy
int p_x;
int p_y;
protected:
};
- circle.h
#include"point.h"
class circle {
public:
void set_r(int r);
void set_o(point c);
int get_r();
point get_o();
private:
//圆心xy
point c_o;
//半径
int c_r;
protected:
};
- point.cpp
#include"point.h"
void point::set_xy(int x, int y) {
p_x = x;
p_y = y;
}
int point::get_x() {
return p_x;
}
int point::get_y() {
return p_y;
}
- circle.cpp
#include"circle.h"
void circle::set_r(int r) {
c_r = r;
}
void circle::set_o(point c) {
c_o = c;
}
int circle::get_r() {
return c_r;
}
point circle::get_o() {
return c_o;
}
- 主函数.cpp
#include"circle.h"
void c_p(circle &c, point &p) {
int distence_cp = (c.get_o().get_x() - p.get_x()) * (c.get_o().get_x() - p.get_x()) + (c.get_o().get_y() - p.get_y()) * (c.get_o().get_x() - p.get_x()) - c.get_r() * c.get_r();
if (distence_cp == 0) {
cout << "点在圆上" << endl;
}
else if (distence_cp > 0) {
cout << "点在圆外" << endl;
}
else {
cout << "点在圆内" << endl;
}
}
int main() {
circle c;
point c_o;
point p1;
point p2;
point p3;
c.set_r(2);
c_o.set_xy(0, 0);
c.set_o(c_o);
p1.set_xy(2, 0);
c_p(c, p1);
p2.set_xy(1, 0);
c_p(c, p2);
p3.set_xy(3, 0);
c_p(c, p3);
...
}
4.2 对象的初始化与清理
4.2.1 构造函数和析构函数
class test{
public:
test(...){
cout << "test的构造函数" << endl ;
}
...
~test(){
cout << "test的析构函数" << endl ;
}
...
};
4.2.2 构造函数的分类及调用
class test{
public:
test(){
cout << "test的无参构造函数" << endl ;
}
...
test(int a){
cout << "test的有参构造函数" << endl ;
}
...
test(const test &t){
cout << "test的拷贝构造函数" << endl ;
}
...
};
//构造函数的调用
void usage(){
//括号法
test t1; //默认构造函数的调用不加()
test t2(10);
test t3(t2);
//显示法
test t1;
test t2 = test(10); //test(10)为匿名对象,当前执行后,系统自动回收
test t3 = test(t2); //不要利用拷贝构造函数初始化匿名对象 test(t2) == test t2; 重定义
//隐式转换法
test t4 = 10; //等价于 test t4 = test(10)
test t5 = t4; //等价于 test t5 = test(t4)
}
4.2.3 拷贝构造函数调用时机
4.2.4 构造函数调用规则
4.2.5 深拷贝与浅拷贝
class person {
public:
int m_age;
int* m_high;
person() {
cout << "person的无参构造函数" << endl;
}
person(int age,int high) {
m_age = age;
m_high = new int(high);
cout << "person的有参构造函数" << endl;
}
person(const person &p) {
m_age = p.m_age;
//m_high = p.m_high;
m_high = new int(*p.m_high); //深拷贝,重新在堆区开辟空间存储
cout << "person的拷贝构造函数" << endl;
}
~person() {
//析构函数释放堆区数据 浅拷贝会重复释放 报错
if (m_high != NULL) {
delete m_high;
m_high = NULL;
}
cout << "tperson的析构构函数" << endl;
}
};
void test() {
person p1(18,170);
person p2(p1);
cout << p1.m_age << *p1.m_high << endl;
cout << p2.m_age << *p2.m_high << endl;
}
int main() {
test();
...
}
4.2.6 初始化列表
class person{
public:
int m_a;
int m_b;
person(int a, int b) : m_a(a), m_b(b){
...
}
...
};
void test(){
person p(1,2);
}
4.2.7 类对象作为类成员
- A先构造,B后构造
- B先析构,A后析构
4.2.8 静态成员
class person {
public:
int m_b;//非静态成员变量
static int m_a;//静态成员变量
static void func() {//静态成员函数有访问权限public、private、protect的区分
m_a = 100;
//m_b = 100;//不可以访问非静态成员变量,无法区分是哪个对象的属性
cout << "static void func调用" << endl;
}
};
int person::m_a = 0;//初始化
void test() {
// 1、通过对象访问
person p1;
p1.func();
// 2、通过类名访问,不属于某个对象
person::func();
}
int main() {
test();
...
}
4.3 C++对象模型和this指针
4.3.1 成员变量和成员函数分开存储
- 空类和空对象所占的内存为 1
4.3.2 this指针概念
class person {
public:
int age;
person(int age) {
//age = age;
this->age = age;
}
//返回类型的应该是 person& 引用,而不是 person ,不然不是本体
person& add(person &p) {
this->age += p.age;
// this 是指向 p2 的指针,则 *this 指向的是 p2 的本体
return *this;
}
};
void test() {
person p1(18);
cout << p1.age << endl;
person p2(10);
p2.add(p1).add(p1); //p2.add()的返回值为 p2 本体,可一直调用
cout << p2.age << endl;
}
int main() {
test();
...
}
4.3.3 空指针访问成员函数
class person {
public:
int m_age;
void show_class(){
cout << "show_class" << endl;
}
void show_age() {
if (this == NULL) {
return;
}
cout << m_age << endl;
}
};
void test() {
person * p = NULL;
p->show_class();
p->show_age(); // 空指针无法找到数据 会报错
}
int main() {
test();
...
}
4.3.4 const修饰成员函数
class person {
public:
int m_age;
mutable int m_AGE; //在常函数中也可以修改
// this 指针的本质是 指针常量 ,指针的指向不能修改
//成员函数的const修饰的是this指针,使其指向的值也不可以修改
void show_person() const
{
//this = NULL; //指针指向不可以修改
//this->m_age = 100; //指针指向的值也不可以修改
this->m_AGE = 100;
}
void func() {}
};
void test() {
person p1;
p1.show_person();
const person p2; //常对象
//p2.m_age = 10; //不可修改其属性
p2.m_AGE = 100; //特殊值
//常对象只能调用常函数
p1.show_person();
p2.show_person();
//p2.func();
}
int main() {
test();
...
}
4.4 友元
4.4.1 全局函数做友元
class building {
//全局函数是building的友元
friend void goodgay(building &build);
public:
building() {
m_sit = "客厅";
m_bed = "卧室";
}
string m_sit;
private:
string m_bed;
};
//全局函数
void goodgay(building &build) {
cout << " 正在访问 " << build.m_sit << endl;
cout << " 正在访问 " << build.m_bed << endl;
}
void test() {
building build1;
goodgay(build1);
}
int main() {
test();
...
}
4.4.2 类做友元
class building {
//类做友元
friend class goodgay;
public:
building();
string m_sit;
private:
string m_bed;
};
class goodgay {
public:
goodgay();
void visit();
building* build;
};
//类外写成员函数
goodgay::goodgay() {
//创建建筑对象
build = new building;
}
void goodgay::visit() {
cout << " 正在访问 " << build->m_sit << endl;
cout << " 正在访问 " << build->m_bed << endl;
}
building::building() {
m_sit = "客厅";
m_bed = "卧室";
}
void test() {
goodgay gay1;
gay1.visit();
}
int main() {
test();
...
}
4.4.3 成员函数做友元
class building;
class goodgay {
public:
goodgay();
void visit();
private:
building* build;
};
class building {
//成员函数做友元
friend void goodgay::visit();
public:
building();
string m_sit;
private:
string m_bed;
};
//类外写成员函数
goodgay::goodgay() {
//创建建筑对象
build = new building;
}
void goodgay::visit() {
cout << " 正在访问 " << build->m_sit << endl;
cout << " 正在访问 " << build->m_bed << endl;
}
building::building() {
m_sit = "客厅";
m_bed = "卧室";
}
void test() {
goodgay g1;
g1.visit();
}
int main() {
test();
...
}
4.5 运算符重载
4.5.1 加号运算符重载
class num {
public:
int m_a;
int m_b;
num() {};
num(int a,int b) {
this->m_a = a;
this->m_b = b;
};
//num operator+(num &num);
};
//成员函数重载
//num num::operator+(num &num1) {
// num num_temp;
// num_temp.m_a = this->m_a + num1.m_a;
// num_temp.m_b = this->m_b + num1.m_b;
// return num_temp;
//}
//全局函数重载
num operator+(num &num1,num &num2) {
num num_temp;
num_temp.m_a = num1.m_a + num2.m_a;
num_temp.m_b = num1.m_b + num2.m_b;
return num_temp;
}
void test() {
num num1(2,4);
num num2(3,5);
num num3 = num1 + num2;
//成员函数调用的本质:num num3 = num1.operator+(num2)
//cout << "成员函数a: "<<num3.m_a << endl;
//cout << "成员函数b: "<<num3.m_b << endl;
//全局函数调用的本质:num num3 = operator+(num1,num2)
cout << "全局函数a: " << num3.m_a << endl;
cout << "全局函数b: " << num3.m_b << endl;
//运算符重载 也可以发生函数重载 即两个operator+的输入参数不同
}
int main() {
test();
...
}
4.5.2 左移运算符重载
class left_move {
friend ostream& operator<<(ostream &cout, left_move &left_1);
public:
left_move(int a,int b) {
this->m_a = a;
this->m_b = b;
}
//p.operator<<(cout)
//不会利用成员函数重载<<运算符,因为无法实现<<在左侧
private:
int m_a;
int m_b;
};
//全局函数重载
ostream& operator<<(ostream &cout, left_move &left_1) {
cout <<" m_a = "<< left_1.m_a << endl;
cout <<" m_b = "<< left_1.m_b << endl;
return cout;
}
void test() {
left_move left_1(1,2);
cout << left_1 << endl;
}
int main() {
test();
...
}
4.5.3 递增运算符重载
class my_int {
friend ostream& operator<<(ostream &cout,my_int my_int);
public:
my_int() {
this->m_num = 0;
}
//前置递增重载 返回的是引用 为了对一个数进行重复操作
my_int& operator++() {
this->m_num++;
return *this;
}
//后置递增重载 返回的是值而不是引用 int用于区分前置和后置
my_int operator++(int) {
my_int temp = *this;
this->m_num++;
return temp;
}
private:
int m_num;
};
//左移重载 对象不加引用,后置返回的temp是不可修改的值
ostream& operator<<(ostream &cout,my_int my_int) {
cout << my_int.m_num << endl;
return cout;
}
void test() {
//前置
my_int my_int1;
cout << my_int1 << endl;
cout << ++my_int1 << endl;
cout << my_int1 << endl;
//后置
my_int my_int2;
cout << my_int2 << endl;
cout << my_int2++ << endl;
cout << my_int2 << endl;
}
int main() {
test();
...
}
4.5.4 赋值运算符重载
class person {
friend void test();
public:
person(int age) {
//在堆区开辟内存存储,并用m_age指针维护
m_age = new int(age);
}
~person() {
if (m_age != NULL) {
delete m_age;
m_age = NULL;
}
}
//赋值重载
person& operator=(person &p) {
//编译器默认:浅拷贝
//m_age = p.m_age;
//先释放本身堆区的内存
if (m_age != NULL) {
delete m_age;
m_age = NULL;
}
//深拷贝
this->m_age = new int(*p.m_age);
return *this;
}
private:
int* m_age;
};
void test(){
person p1(17);
person p2(24);
person p3(38);
p3 = p2 = p1;
cout << *p1.m_age << "\t" << *p2.m_age << "\t" << *p3.m_age << endl;
}
int main() {
test();
...
}
4.5.5 关系运算符重载
class person {
public:
person(string name,int age) {
this->m_name = name;
this->m_age = age;
}
//重载 ==
bool operator==(person &p) {
if (this->m_name == p.m_name && this->m_age == p.m_age) {
return true;
}
return false;
}
private:
string m_name;
int m_age;
};
void test() {
person p1("a", 1);
person p2("b", 1);
if (p1 == p2) {
cout << " 1 , 2相等 " << endl;
}
else {
cout << " 1 , 2不等 " << endl;
}
}
int main() {
test();
...
}
4.5.6 函数调用运算符重载
class my_add {
public:
int operator()(int a,int b) {
return a + b;
}
private:
};
void test() {
my_add add1;
int ret = add1(1,1);
cout << ret << endl;
//匿名函数对象:my_add()
cout << my_add()(2,2) << endl;
}
int main() {
test();
...
}
4.6 继承
4.6.1 继承的基本语法
//公共页面
class comm {
public:
void header() {
cout << "h1,h2,h3,..." << endl;
}
void footer() {
cout << "f1,f2,f3,..." << endl;
}
};
//继承
class java : public comm {
public:
void content() {
cout << "JAVA" << endl;
}
};
class python : public comm {
public:
void content() {
cout << "PYTHON" << endl;
}
};
void test() {
//cout << "JAVA界面" << endl;
python ja;
ja.header();
ja.content();
ja.footer();
//cout << "PYthon界面" << endl;
java py;
py.header();
py.content();
py.footer();
}
int main() {
test();
...
}
4.6.2 继承方式
4.6.3 继承中的对象模型
class base {
public:
int m_a;
protected:
int m_b;
private:
int m_c;
};
class son : public base {
public:
int m_d;
};
void test() {
//父类中所有的非静态成员属性都会被子类继承
cout << sizeof(son) << endl;
}
int main() {
test();
...
}
4.6.4 继承中构造和析构顺序
class base {
public:
base() {
cout << "base的构造函数" << endl;
}
~base() {
cout << "base的析构函数" << endl;
}
};
class son : public base {
public:
son() {
cout << "son的构造函数" << endl;
}
~son() {
cout << "son的析构函数" << endl;
}
};
void test() {
son s1;
}
int main() {
test();
...
}
- 构造:先构造父类,再构造子类
- 析构:先析构子类,在析构父类
4.6.5 继承同名成员处理方式
class base {
public:
int m_age;
base() {
m_age = 70;
}
void func() {
cout << "base -- func" << endl;
}
};
class son : public base {
public:
int m_age;
son() {
m_age = 40;
}
void func() {
cout << "son -- func" << endl;
}
};
void test() {
son s1;
//同名变量
cout << s1.m_age << endl;
cout << s1.base::m_age << endl;
//同名函数
s1.func();
s1.base::func();
}
int main() {
test();
...
}
4.6.6 继承同名静态成员处理方式
class base {
public:
//类内声明 类外初始化
static int m_age;
static void func() {
cout << "base -- func" << endl;
}
};
int base::m_age = 70;
class son : public base {
public:
static int m_age;
static void func() {
cout << "son -- func" << endl;
}
};
int son::m_age = 30;
void test() {
//通过对象访问
son s1;
cout << s1.m_age << endl;
cout << s1.base::m_age << endl;
s1.func();
s1.base::func();
//通过类名访问
cout << son::m_age << endl;
cout << son::base::m_age << endl;
son::func();
son::base::func();
}
int main() {
test();
...
}
4.6.7 多继承语法
class base1 {
public:
int m_a;
base1() {
m_a = 70;
}
};
class base2 {
public:
int m_a;
base2() {
m_a = 60;
}
};
class son : public base1 , public base2 {
public:
int m_a;
son() {
m_a = 30;
}
};
void test() {
son s1;
cout << sizeof(s1) << endl;
cout << s1.m_a << endl;
cout << s1.base1::m_a << endl;
cout << s1.base2::m_a << endl;
}
int main() {
test();
...
}
4.6.8 菱形继承
class animal {
public:
int m_age;
animal() {
m_age = 18;
}
};
//利用虚继承(实际继承的为指针--其指向的是偏移table) 解决菱形继承问题
//在继承前加上关键字 virtual
//父类(animal)称为虚基类
class sheep : virtual public animal {};
class tuo : virtual public animal {};
class sheep_tuo : public sheep , public tuo {};
void test() {
sheep_tuo st1;
cout << st1.m_age << endl;
cout << st1.sheep::m_age << endl;
cout << st1.tuo::m_age << endl;
st1.sheep::m_age = 100;
cout << st1.sheep::animal::m_age << endl;
cout << st1.m_age << endl;
cout << st1.sheep::m_age << endl;
cout << st1.tuo::m_age << endl;
}
int main() {
test();
...
}
4.7 多态
4.7.1 多态的基本概念
class animal {
public:
//虚函数 可以让dospeak函数地址 -- 晚绑定
virtual void speak() {
cout << "animal - - speak" << endl;
}
};
class cat : public animal {
public:
void speak() {
cout << "cat - - speak" << endl;
}
};
//函数地址会在编译阶段 -- 早绑定
//父类和子类的类型可以同用 不用转换 animal &animal = cat
void dospeak(animal &animal) {
animal.speak();
}
void test() {
cat c1;
dospeak(c1);
}
int main() {
test();
...
}
4.7.2 多态案例一 计算器类
- 普通写法
class cacul {
public:
int num_a;
int num_b;
string oper;
cacul(int num_a, int num_b, string oper) {
this->num_a = num_a;
this->num_b = num_b;
this->oper = oper;
};
int getresult(string oper) {
if (oper == "+") {
return num_a + num_b;
}
else if (oper == "-") {
return num_a - num_b;
}
else if (oper == "*") {
return num_a * num_b;
}
}
};
void test() {
cacul c1(4, 2, "*");
cout << c1.getresult(c1.oper) << endl;
int main() {
test();
...
}
- 多态技术
class abs_cacul {
public:
int m_num1; //操作数1
int m_num2; //操作数2
//纯虚函数 在父类中无意义 主要是调用子类重写的内容
virtual void getresult(int m_num1, int m_num2) = 0;
};
//加法
class add_cacul : public abs_cacul {
public:
virtual void getresult(int m_num1, int m_num2) {
cout << m_num1 + m_num2 << endl;
return ;
}
};
//减法
class sub_cacul : public abs_cacul {
public:
virtual void getresult(int m_num1, int m_num2) {
cout << m_num1 - m_num2 << endl;;
return ;
}
};
//乘法
class mul_cacul : public abs_cacul {
public:
virtual void getresult(int m_num1, int m_num2) {
cout << m_num1 * m_num2 << endl;
return ;
}
};
//除法
class div_cacul : public abs_cacul {
public:
virtual void getresult(int m_num1, int m_num2) {
cout << m_num1 / m_num2 << "..." << m_num1 % m_num2 << endl;
return ;
}
};
void test() {
//创建加法
abs_cacul* abs = new add_cacul; //实例化对象
abs->getresult(5, 2);
delete abs;
//创建减法
abs = new sub_cacul;
abs->getresult(5, 2);
delete abs;
//创建乘法
abs = new mul_cacul;
abs->getresult(5, 2);
delete abs;
//创建除法
abs = new div_cacul;
abs->getresult(5, 2);
delete abs;
}
int main() {
test();
...
}
4.7.3 纯虚函数和抽象类
//只有一个纯虚函数的类为抽象类
class base {
public:
virtual void func() = 0;
};
class son :public base {
public:
virtual void func() {
cout << "子类必须重写父类中的纯虚函数,否则无法实例化对象" << endl;
}
};
void test() {
base* base = new son; //创建对象
base->func();
delete base;
}
int main() {
test();
...
}
4.7.4 多态案例二 制作饮品
class make {
public:
virtual void boil() = 0;
virtual void brew() = 0;
virtual void pour() = 0;
virtual void puts() = 0;
virtual void loop() {
boil();
brew();
pour();
puts();
}
};
class coffee :public make {
public:
virtual void boil() {
cout << " 煮百岁山" << endl;
}
virtual void brew() {
cout << " 冲泡咖啡" << endl;
}
virtual void pour() {
cout << " 倒入马克杯" << endl;
}
virtual void puts() {
cout << " 加糖和牛奶" << endl;
}
virtual void loop() {
cout << " 来杯卡布奇诺:" << endl;
boil();
brew();
pour();
puts();
cout << endl;
}
};
class tea :public make {
public:
virtual void boil() {
cout << " 煮山泉水" << endl;
}
virtual void brew() {
cout << " 冲泡茶叶" << endl;
}
virtual void pour() {
cout << " 倒入紫砂壶" << endl;
}
virtual void puts() {
cout << " 加菊和枸杞" << endl;
}
virtual void loop() {
cout << " 来壶铁观音:" << endl;
boil();
brew();
pour();
puts();
cout << endl;
}
};
void do_drink(make* select) {
select->loop();
delete select; // 释放堆区数据
}
void test() {
//制作咖啡
do_drink(new coffee);
//制作茶叶
do_drink(new tea);
}
int main() {
test();
...
}
4.7.5 虚析构和纯虚析构
class animal {
public:
virtual void speak() = 0;
animal() {
cout << "annimal的构造" << endl;
}
//虚析构会调用子类的析构函数
//virtual ~animal() {
// cout << "annimal的虚析构" << endl;
//}
//纯虚析构 既需要声明 也需要实现
virtual ~animal() = 0;
};
//纯虚析构的实现
animal::~animal() {
cout << "annimal的纯虚析构" << endl;
}
class cat :public animal {
public:
string* m_name;
virtual void speak() {
cout << *this->m_name << "cat在说话" << endl;
}
cat(string m_name) {
cout << "cat的构造" << endl;
this->m_name = new string(m_name);
}
~cat() {
cout << "cat的析构" << endl;
if (m_name != NULL) {
delete m_name;
m_name = NULL;
return;
}
}
};
void test() {
animal* animal = new cat("Tom");
animal->speak();
//父类指针在析构时,不会调用子类的的析构函数
//利用虚析构解决
delete animal;
}
int main() {
test();
...
}
4.7.6 多态案例三 电脑组装
//虚基类
class cpu {
public:
virtual void cacul() = 0;
};
class memory {
public:
virtual void storage() = 0;
};
//asua零件类
class asus_cpu :public cpu {
public:
virtual void cacul() {
cout << "asus的cpu" << endl;
}
};
class asus_mem :public memory{
public:
virtual void storage() {
cout << "asus的显卡" << endl;
}
};
//lenovo零件类
class lenovo_cpu :public cpu {
public:
virtual void cacul() {
cout << "lenovo 的 cpu" << endl;
}
};
class lenovo_mem : public memory{
public:
virtual void storage() {
cout << "lenovo 的显卡" << endl;
}
};
//电脑组装
class computer {
public:
cpu * m_cpu;
memory * m_mem;
computer(cpu* cpu ,memory* mem) {
this->m_cpu = cpu;
this->m_mem = mem;
}
~computer() {
//释放cpu和内存条的零件指针
if (m_cpu != null) {
delete m_cpu;
m_cpu = null;
}
if (m_mem != null) {
delete m_mem;
m_mem = null;
}
return;
}
void dowork() {
m_cpu->cacul();
m_mem->storage();
}
};
void test() {
cpu * cpu = new asus_cpu;
memory * mem = new lenovo_mem;
computer * c1 = new computer(cpu,mem);
c1->dowork();
delete c1;
}
int main() {
test();
...
}
5 文件操作
5.1 文本文件
5.1.1 写文件
void test() {
ofstream ofs;
ofs.open("C:/Users/yong/Desktop/test.txt", ios::out);
ofs << "test1" << endl;
ofs << "test2" << endl;
ofs.close();
}
int main() {
test();
...
}
5.1.2 读文件
void test() {
ifstream ifs;
ifs.open("C:/Users/yong/Desktop/test.txt", ios::in);
if (!ifs.is_open()) {
cout << "test.txt打开失败!!!" << endl;
return;
}
//读数据
//第一种
/*char buf[1024] = { 0 };
while (ifs >> buf) {
cout << buf << endl;
}*/
//第二种
/*char buf[1024] = { 0 };
while (ifs.getline(buf, sizeof(buf))) {
cout << buf << endl;
}*/
//第三种
string buf;
while (getline(ifs, buf)) {
cout << buf << endl;
}
//第四种 不常用 一个一个读 效率低
/*char c;
while ((c = ifs.get()) != EOF) { //EOF:end of file 文件尾的标志
cout << c << endl;
}*/
ifs.close();
}
int main() {
test();
...
}
5.2 二进制文件
5.2.1 写文件
class person {
public:
char m_name[64];
int m_age;
};
void test() {
ofstream ofs;
ofs.open("C:/Users/yong/Desktop/test2.txt", ios::out | ios::binary);
person p1 = { "张三", 18 };
ofs.write((const char*)&p1, sizeof(p1));
ofs.close();
}
int main() {
test();
...
}
5.2.2 读文件
class person {
public:
char m_name[64];
int m_age;
};
void test() {
ifstream ifs;
ifs.open("C:/Users/yong/Desktop/test2.txt", ios::in | ios::binary);
if (!ifs.is_open()) {
cout << "test2.txt打开失败!!!" << endl;
return;
}
person p;
ifs.read((char*)&p, sizeof(p));
cout << p.m_name << "\t" <<p.m_age << endl;
ifs.close();
}
int main() {
test();
...
}