C++执行时,内存大方向划分为4个区域
程序编译后,生成了exe,未执行程序前
代码区:
存放CPU执行的机器指令
**特点:**共享的:频繁执行代码,只需保存一份
只读的:防止程序意外修改
全局区:
存放全局变量和静态变量
包含常量区:存放字符串常量和其他常量
该区域的数据在程序结束后被操作系统释放
示例:
#include
using namespace std;
int g_a = 1;
int g_b = 1;
const int g_c = 4;
const int g_d = 4;
int main() {
int a = 2;
int b = 2;
static int s_a = 3;
static int s_b = 3;
cout << "局部变量a " << (int)&a << endl;
cout << "局部变量b " << (int)&b << endl;
cout << "全局变量a " << (int)&g_a << endl;
cout << "全局变量b " << (int)&g_b << endl;
cout << "静态变量a " << (int)&s_a << endl;
cout << "静态变量b " << (int)&s_b << endl;
cout << "字符串常量" << (int)&"hello" << endl;
cout << "全局常量c " << (int)&g_c << endl;
cout << "全局常量d " << (int)&g_d << endl;
const int c = 5;
const int d = 5;
cout << "局部常量c " << (int)&c << endl;
cout << "局部常量d " << (int)&d << endl;
system("pause");
return 0;
}
栈区:
编译器自动分配释放,存放函数的参数值,局部变量等
注意:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放
示例:
# include
using namespace std;
int* func() {
int a = 100;
return &a;
}
int main() {
int* p = func();
cout << *p << endl;
cout << *p << endl;
cout << *p << endl;
system("pause");
return 0;
}
注意 VS2022(64位)地址一直保留
堆区:
由程序员分配和释放,如果程序员不释放,程序结束时由操作系统回收
主要利用new在堆区开辟内存
示例:
# include
using namespace std;
int* func() {
int* p = new int(10);
return p;
}
int main() {
// 指针本质上也是局部变量,放在栈上,指针保存的数据放在堆区
int* p = func();
cout << *p << endl;
cout << *p << endl;
system("pause");
return 0;
}
new
操作符在堆区开辟数据delete
示例:
# include
using namespace std;
int* func() {
int* p = new int(10);
return p;
}
void test01() {
int* p = func();
cout << *p << endl;
cout << *p << endl;
delete(p);
//cout << *p << endl;
}
void test02() {
int* arr = new int[10];
for (int i = 0; i < 10; i++) {
arr[i] = i;
}
for (int i = 0; i < 10; i++) {
cout << arr[i] << endl;
}
delete[] arr;
}
int main() {
test01();
test02();
system("pause");
return 0;
}
数据类型 &别名 = 原名
示例:
# include
using namespace std;
int main() {
int a = 10;
int& b = a;
cout << a << endl;
cout << b << endl;
b = 100;
cout << a << endl;
cout << b << endl;
int c = 20;
b = c;
cout << a << endl;
cout << b << endl;
cout << c << endl;
system("pause");
return 0;
}
引用做函数参数
引用做函数返回值
不要返回局部变量的引用
函数的调用可以作为左值
示例:
# include
using namespace std;
void swap(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
int& test01() {
int a = 10;
return a;
}
int& test02() {
static int a = 90;
return a;
}
int main() {
int a = 10;
int b = 20;
swap(a, b);
cout << a << endl;
cout << b << endl;
int& ref1 = test01();
cout << ref1 << endl;
cout << ref1 << endl;
int& ref2 = test02();
cout << ref2 << endl;
cout << ref2 << endl;
test02() = 190;
cout << ref2 << endl;
cout << ref2 << endl;
system("pause");
return 0;
}
本质上是指针常量
int& ref = a 相当于 int* const ref = &a
ref = 20 相当于 *ref = 20
**作用:**常量引用主要用来修饰形参,防止误操作
在函数形参列表中,可以加const
修饰形参,防止形参改变实参
示例:
# include
using namespace std;
void show(const int& val) {
cout << val << endl;
}
int main() {
const int& ref = 10;// 相当于 int temp = 10; const int& ref = temp;
// 加上 const 变成只读 不可修改
int a = 100;
show(a);
system("pause");
return 0;
}
语法:返回值类型 函数名 (参数 默认值)
注意:
示例:
# include
using namespace std;
int sum(int a, int b = 20, int c = 30) {
return a + b + c;
}
int main() {
cout << sum(10) << endl;
cout << sum(10, 30) << endl;
system("pause");
return 0;
}
语法:返回值类型 函数名 (数据类型){}
示例:
# include
using namespace std;
int sum(int a, int) {
return a;
}
int main() {
cout << sum(10, 30) << endl;
system("pause");
return 0;
}
**作用:**函数名可以相同,提高复用性
满足条件:
**注意:**函数重载的返回值不可以作为函数重载的条件
示例:
# include
using namespace std;
void sum() {
cout << "aaa" << endl;
}
void sum(int a) {
cout << "int" << endl;
}
void sum(double a) {
cout << "double" << endl;
}
void sum(double a, int b) {
cout << "double,int" << endl;
}
void sum(int a, double b) {
cout << "int,double" << endl;
}
//注意事项
//int sum(int a, double b) {
// cout << "int,double" << endl;
//}
int main() {
sum();
sum(10);
sum(10.0);
sum(3.14, 10);
sum(10, 3.13);
system("pause");
return 0;
}
注意事项:
# include
using namespace std;
//引用作为重载的条件
void func(int& a) {
cout << "void func(int& a)" << endl;
}
void func(const int& a) {
cout << "void func(const int& a)" << endl;
}
//函数重载碰到默认参数
void func2(int a, int b = 10) {
cout << "a,b" << endl;
}
void func2(int a) {
cout << "a" << endl;
}
int main() {
int a;
func(a);
func(10);
//func2(10);
system("pause");
return 0;
}
意义:
示例:
# include
using namespace std;
class Circle{
public:
//属性
int r;
//行为
double func() {
return 2 * 3.14 * r;
}
void setR(int R) {
r = R;
}
};
int main() {
Circle c;
c.r = 10;
cout << c.func();
return 0;
}
访问权限:
public | 类内可以访问 | 类外可以访问 | |
---|---|---|---|
protected | 类内可以访问 | 类外不可访问 | 可以访问父类的保护内容 |
private | 类内可以访问 | 类外不可访问 | 不可以访问父类的私有内容 |
示例:
# include
# include
using namespace std;
class Person{
public:
string name;
protected:
string car;
private:
string password;
};
int main() {
Person nb;
nb.name = "nb";
//nb.car;
//nb.password;
cout << nb.name;
return 0;
}
struct与class的区别:
成员属性设置为私有:
示例:
# include
# include
using namespace std;
class Person{
public:
void setname(string name) {
m_name = name;
}
string getname() {
return m_name;
}
void setage(int age) {
if (age < 0 || age > 160) {
cout << "error";
return;
}
m_age = age;
}
int getage() {
return m_age;
}
void setid(int id) {
m_id = id;
}
private:
string m_name;
int m_age = 8;
int m_id = 1;
};
int main() {
Person p;
p.setname("王小明");
cout << p.getname() << " " << p.getage() << endl;
return 0;
}
构造函数和析构函数:
我们不提供析构和构造的话,编译器提供的是空实现。
构造函数语法:类名(){}
析构函数语法:~类名(){}
相同点:
不同点:
# include
using namespace std;
class Person{
public:
Person() {
cout << "1" << endl;
}
~Person() {
cout << "2" << endl;
}
};
void test01() {
Person p;
}
int main() {
//test01();
Person p;
system("pause");
return 0;
}
构造函数的分类和调用:
两种分类方式:
三种调用方式:
# include
using namespace std;
class Person{
public:
Person() {
cout << "无参构造" << endl;
}
Person(int a) {
age = a;
cout << "有参构造" << endl;
}
Person(const Person& p) {
age = p.age;
cout << "拷贝构造" << endl;
}
~Person() {
cout << "析构" << endl;
}
int age;
};
void test01() {
//括号法
//Person p1;
//Person p2(10);
//Person p3(p2);
//注意:
//调用默认构造函数时,不要加(),编译器会认为是一个函数的声明
//cout << "p2年龄为:" << p2.age << endl;
//cout << "p3年龄为:" << p3.age << endl;
//显示法
Person p1;
Person p2 = Person(10);
Person p3 = Person(p2);
//Person(10) 匿名对象 当前行结束 系统自动回收
//Person(p2) 不能利用拷贝构造函数 初始化匿名对象
// 编译器会认为 Person (p3) 相当于 Person p3
//隐式转换
Person p4 = 20; // 相当于 Person p4 = Person(20)
Person p5 = p4;
}
int main() {
test01();
system("pause");
return 0;
}
拷贝构造函数的调用时机:
三种情况:
# include
using namespace std;
class Person{
public:
Person() {
cout << "无参构造" << endl;
}
Person(int a) {
age = a;
cout << "有参构造" << endl;
}
Person(const Person& p) {
age = p.age;
cout << "拷贝构造" << endl;
}
~Person() {
cout << "析构" << endl;
}
int age;
};
//使用一个已经创建完毕的对象来初始化一个新对象
void test01() {
Person p1(20);
Person p2(p1);
cout << "p2年龄为:" << p2.age << endl;
}
//值传递的方式给函数参数传值
void doWork02(Person p) {
}
void test02() {
Person p;
doWork02(p);
}
//值方式返回局部对象
Person doWork03() {
Person p1;
return p1;
}
void test03() {
Person p = doWork03();
}
int main() {
test03();
system("pause");
return 0;
}
构造函数调用规则:
默认情况下,C++编译器至少给一个类添加3个函数
调用规则:
# include
using namespace std;
class Person{
public:
//Person() {
// cout << "无参构造" << endl;
//}
Person(int a) {
age = a;
cout << "有参构造" << endl;
}
//Person(const Person& p) {
// age = p.age;
// cout << "拷贝构造" << endl;
//}
~Person() {
cout << "析构" << endl;
}
int age;
};
//void test01() {
// Person p1;
// p1.age = 10;
// Person p2(p1);
// cout << "p2年龄为:" << p2.age << endl;
//}
//如果用户定义有参构造函数,C++不在提供默认无参构造,但是会提供默认拷贝构造
void test02() {
Person p(28);
Person p2(p);
cout << "p2年龄为:" << p2.age << endl;
}
int main() {
test02();
system("pause");
return 0;
}
深拷贝与浅拷贝:
# include
using namespace std;
class Person{
public:
Person() {
cout << "无参构造" << endl;
}
Person(int a,int h) {
age = a;
height = new int(h);
cout << "有参构造" << endl;
}
Person(const Person& p) {
age = p.age;
//height = p.height; // 编译器浅拷贝
height = new int(*p.height);
cout << "拷贝构造" << endl;
}
~Person() {
if (height != NULL) {
delete height;
height = NULL;
}
cout << "析构" << endl;
}
int age;
int* height;
};
void test01() {
Person p1(18, 180);
cout << "p1年龄为:" << p1.age << " p1身高为:" << *p1.height << endl;
Person p2(p1);
cout << "p2年龄为:" << p2.age << " p2身高为:" << *p2.height << endl;
}
int main() {
test01();
system("pause");
return 0;
}
初始化列表:
语法:构造函数(): 属性1(值1),属性2(值2) ...{}
# include
using namespace std;
class Person{
public:
Person(int pa, int pb, int pc) : a(pa), b(pb), c(pc) {
}
int a;
int b;
int c;
};
void test01() {
Person p(10, 20, 30);
cout << p.a << " " << p.b << " " << p.c << endl;
}
int main() {
test01();
system("pause");
return 0;
}
对象成员:
class A {}
class B {
A a;
}
示例:顺序:手机构造->人构造->人析构->手机析构
# include
# include
using namespace std;
class Phone {
public:
Phone(string name) {
m_Pname = name;
cout << "手机构造" << endl;
}
~Phone() {
cout << "手机析构" << endl;
}
string m_Pname;
};
class Person{
public:
Person(string name, string Pname) : m_name(name), m_phone(Pname) {
cout << "人构造" << endl;
}
~Person() {
cout << "人析构" << endl;
}
string m_name;
Phone m_phone;
};
void test01() {
Person p("张三", "苹果");
}
int main() {
test01();
system("pause");
return 0;
}
静态成员:
静态成员变量:
静态成员函数:
示例1:
# include
# include
using namespace std;
class Person{
public:
static int a;
private:
static int b;
};
int Person::a = 10;
int Person::b = 20;
void test01() {
Person p1;
cout << p1.a << endl;
Person p2;
p2.a = 20;
//两种访问方式
cout << p1.a << endl;
cout << Person::a << endl;
//cout << Person::b << endl;
}
int main() {
test01();
system("pause");
return 0;
}
示例2:
# include
# include
using namespace std;
class Person{
public:
static void func() {
a = 100;
//b = 200; 可能有多个对象包含不同的b 不知道修改哪个b
cout << "static void func调用" << endl;
}
int b;
static int a;
};
int Person::a = 1000;
void test01() {
Person p1;
p1.func();
Person::func();
}
int main() {
test01();
system("pause");
return 0;
}
成员变量和成员函数分开存储:
# include
# include
using namespace std;
class Person {
static int a; // 不属于类对象
int b; // 属于类对象
void func(){} // 不属于类对象
static void fun(){} //不属于类对象
};
int Person::a = 1;
void test01() {
//空对象sizeof为1
Person p;
cout << sizeof(p) << endl;
}
int main() {
test01();
system("pause");
return 0;
}
this指针:
this指针指向被调用的成员函数所属的对象
this指针是隐含每一个非静态成员函数内的一种指针
this指针不需要定义,直接使用即可
用途:
# include
# include
using namespace std;
class Person {
public:
int age;
Person(int age) {
this->age = age;
}
//返回Person 值传递调用拷贝构造函数 创建一个新对象 p2-p2'-p2''-p2'''
Person& PersonAddAge(Person& p) {
this->age += p.age;
return *this;
}
};
void test01() {
Person p1(10);
Person p2(10);
p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);
cout << p2.age << endl;
}
int main() {
test01();
system("pause");
return 0;
}
空指针访问成员函数:
# include
# include
using namespace std;
class Person {
public:
void show1() {
cout << "1" << endl;
}
void show2() {
if (this == NULL) {
return;
}
cout << this->b << endl;
}
int b;
};
void test01() {
Person* p = NULL;
p->show1();
p->show2();
}
int main() {
test01();
system("pause");
return 0;
}
const修饰成员函数:
常函数:
常对象:
# include
# include
using namespace std;
class Person {
public:
//相当于 const Person* const this
void show() const{
//this 本质是指针常量 指向不可修改 相当于 Person* const this
//this = NULL;
//this->m_a = 10;
this->m_b = 20;
}
void func(){}
int m_a;
mutable int m_b;
};
void test01() {
Person p1;
p1.show();
const Person p2;
//p2.m_a = 10;
p2.m_b = 90;
p2.show();
//p2.func();
}
int main() {
test01();
system("pause");
return 0;
}
目的:让一个函数或者类访问另一个类中私有成员
关键字:friend
三种实现:
全局函数:
# include
# include
using namespace std;
class Building {
//全局函数做友元
friend void test01(Building* b);
public:
Building() {
this->m_LivingRoom = "客厅";
this->m_BedRoom = "卧室";
}
string m_LivingRoom;
private:
string m_BedRoom;
};
void test01(Building *b) {
cout << b->m_LivingRoom << endl;
cout << b->m_BedRoom << endl;
}
int main() {
Building b;
test01(&b);
system("pause");
return 0;
}
类:
# include
# include
using namespace std;
class Building;
class GoodGay {
public:
GoodGay();
void visit();
Building* building;
};
class Building {
//类使用友元
friend class GoodGay;
public:
Building() {
this->m_LivingRoom = "客厅";
this->m_BedRoom = "卧室";
}
string m_LivingRoom;
private:
string m_BedRoom;
};
GoodGay::GoodGay() {
building = new Building;
}
void GoodGay::visit() {
cout << building->m_LivingRoom << endl;
cout << building->m_BedRoom << endl;
}
void test01() {
GoodGay g;
g.visit();
}
int main() {
test01();
system("pause");
return 0;
}
成员函数:
# include
# include
using namespace std;
class Building;
class GoodGay {
public:
GoodGay();
void visit1();
Building* building;
};
class Building {
//成员函数使用友元
friend void GoodGay::visit1();
public:
Building() {
this->m_LivingRoom = "客厅";
this->m_BedRoom = "卧室";
}
string m_LivingRoom;
private:
string m_BedRoom;
};
GoodGay::GoodGay() {
building = new Building;
}
void GoodGay::visit1() {
cout << building->m_LivingRoom << endl;
cout << building->m_BedRoom << endl;
}
void test01() {
GoodGay g;
g.visit1();
}
int main() {
test01();
system("pause");
return 0;
}
加法:
# include
# include
using namespace std;
class Person {
public:
Person() {
this->m_a = 10;
this->m_b = 20;
}
//成员函数重载
//本质 p3 = p1.operator+(p2)
//Person operator+(Person& p) {
// Person temp;
// temp.m_a = p.m_a + this->m_a;
// temp.m_b = p.m_b + this->m_b;
// return temp;
//}
int m_a;
int m_b;
};
//全局函数重载
//本质 p3 = operator+(p1, p2)
Person operator+(Person& p1, Person& p2) {
Person temp;
temp.m_a = p1.m_a + p2.m_a;
temp.m_b = p1.m_b + p2.m_b;
return temp;
}
void test01() {
Person p1;
Person p2;
Person p3 = p1 + p2;
cout << p3.m_a << endl;
cout << p3.m_b << endl;
}
int main() {
test01();
system("pause");
return 0;
}
左移:
# include
# include
using namespace std;
class Person {
public:
Person() {
this->m_a = 10;
this->m_b = 20;
}
//成员函数无法实现 p.operator << (cout) 相当于 p << cout
//void operator<<(cout) {
//
//}
int m_a;
int m_b;
};
//全局函数实现
ostream& operator<<(ostream& cout, Person& p) {
cout << p.m_a << " " << p.m_b << endl;
return cout;
}
void test01() {
Person p;
cout << p << endl;
}
int main() {
test01();
system("pause");
return 0;
}
递增:
# include
# include
using namespace std;
class Person {
public:
Person() {
this->m_a = 10;
}
//前置++重载
Person& operator++() {
m_a++;
return *this;
}
//后置++重载
Person operator++(int) {
Person temp = *this;
m_a++;
return temp;
}
int m_a;
};
//全局函数实现
ostream& operator<<(ostream& cout, Person p) {
cout << p.m_a << " " << endl;
return cout;
}
void test01() {
Person p;
cout << ++(++p) << endl;
cout << p << endl;
}
void test02() {
Person p;
cout << (p++) << endl;
cout << p << endl;
}
int main() {
test01();
test02();
system("pause");
return 0;
}
赋值:
# include
# include
using namespace std;
class Person {
public:
Person(int a) {
m_a = new int(a);
}
~Person() {
if (m_a != NULL) {
delete m_a;
m_a = NULL;
}
}
Person& operator=(Person &p) {
//先释放堆区的内存 即20
if (m_a != NULL) {
delete m_a;
m_a = NULL;
}
m_a = new int(*p.m_a);
return *this;
}
int *m_a;
};
void test01() {
Person p1(18);
Person p2(20);
Person p3(30);
p3 = p2 = p1;
cout << *p1.m_a << endl;
cout << *p2.m_a << endl;
cout << *p3.m_a << endl;
}
int main() {
test01();
system("pause");
return 0;
}
关系:
# include
# include
using namespace std;
class Person {
public:
Person(int a, int b) {
m_a = a;
m_b = b;
}
bool operator==(Person& p) {
if (this->m_a == p.m_a && this->m_b == p.m_b) {
return true;
}
return false;
}
bool operator!=(Person& p) {
if (this->m_a == p.m_a && this->m_b == p.m_b) {
return false;
}
return true;
}
int m_a;
int m_b;
};
void test01() {
Person p1(10, 20);
Person p2(10, 20);
if (p1 == p2) {
cout << "p1 == p2" << endl;
}
if (p1 != p2) {
cout << "p1 != p2" << endl;
}
}
int main() {
test01();
system("pause");
return 0;
}
函数调用:
# include
# include
using namespace std;
class Person {
public:
Person(int a, int b) {
m_a = a;
m_b = b;
}
//int operator()(int x, int y) {
// return x + y;
//}
void operator()(string text) {
cout << text << endl;
}
int m_a;
int m_b;
};
void test01() {
//int ans = Person(10, 20)(10, 20);
//cout << ans << endl;
Person(10, 20)("hello world");
}
int main() {
test01();
system("pause");
return 0;
}
继承的目的:减少重复的代码
语法:class 子类 : 继承方式 父类
# include
# include
using namespace std;
class Base {
public:
void header() {
cout << "首页 番剧 直播..." << endl;
}
void footer() {
cout << "国创 时尚 动画..." << endl;
}
};
class Java : public Base {
public:
void Tool() {
cout << "Java视频" << endl;
}
};
class Python : public Base {
public:
void Tool() {
cout << "Python视频" << endl;
}
};
void test01() {
Java j;
j.footer();
j.Tool();
Python py;
py.header();
py.Tool();
}
int main() {
test01();
system("pause");
return 0;
}
继承方式:
# include
# include
using namespace std;
class Base {
public:
int a;
protected:
int b;
private:
int c;
};
class Son1 : public Base {
public:
void change() {
a = 10;
b = 20;
//c = 30;
}
};
class Son2 : protected Base {
public:
void change() {
a = 10;
b = 20;
//c = 30;
}
};
class Son3 : private Base {
public:
void change() {
a = 10;
b = 20;
//c = 30;
}
};
class GrandSon3 : private Son3 {
public:
void change() {
//a = 10;
//b = 20;
//c = 30;
}
};
void test01() {
Son1 s1;
s1.a = 11;
//s1.b = 21;
Son2 s2;
//s2.a = 11;
//s2.b = 21;
}
int main() {
test01();
system("pause");
return 0;
}
对象模型:
父类中的所有非静态成员属性都会被子类继承下去
# include
# include
using namespace std;
class Base {
public:
int a;
protected:
int b;
private:
int c;
};
class Son1 : public Base {
public:
int d;
};
void test01() {
Son1 s1;
cout << sizeof(s1) << endl;
}
int main() {
test01();
system("pause");
return 0;
}
继承中构造和析构的顺序:
构造和析构的顺序:先进后出
同名成员处理:
# include
# include
using namespace std;
class Base {
public:
int a = 20;
void func() {
cout << "base func()" << endl;
}
void func(int m) {
cout << "base func(" << m << ")" << endl;
}
protected:
int b;
private:
int c;
};
class Son1 : public Base {
public:
Son1() {
a = 10;
}
int a;
void func() {
cout << "Son1 func()" << endl;
}
};
void test01() {
Son1 s1;
cout << s1.a << endl;
cout << s1.Base::a << endl;
s1.func();
s1.Base::func();
s1.Base::func(2);
}
int main() {
test01();
system("pause");
return 0;
}
# include
# include
using namespace std;
class Base {
public:
static int a;
static void func() {
cout << "Base func()" << endl;
}
static void func(int m) {
cout << "Base func(" << m << ")" << endl;
}
};
int Base::a = 10;
class Son1 : public Base {
public:
static int a;
static void func() {
cout << "Son1 func()" << endl;
}
};
int Son1::a = 20;
void test01() {
Son1 s;
cout << s.a << endl;
cout << s.Base::a << endl;
cout << Son1::a << endl;
cout << Son1::Base::a << endl;
s.func();
s.Base::func();
s.Base::func(3);
Son1::Base::func();
Son1::Base::func(3);
}
int main() {
test01();
system("pause");
return 0;
}
多继承:
语法:class 子类 : 继承方式 父类1 , 继承方式 父类2...
不建议使用
# include
# include
using namespace std;
class Animal {
public:
int age;
};
class Sheep : virtual public Animal{};
class Tuo : virtual public Animal{};
class SheepTuo : public Sheep , public Tuo{};
void test01() {
SheepTuo st;
st.Sheep::age = 10;
st.Tuo::age = 9;
cout << st.Sheep::age << endl;
cout << st.Tuo::age << endl;
cout << st.age << endl;
}
int main() {
test01();
system("pause");
return 0;
}
总结:
基本概念:
多态分为两类:
区别:
# include
# include
using namespace std;
class Animal {
public:
virtual void Speak() {
cout << "动物叫" << endl;
}
};
class Cat : public Animal {
public:
void Speak() {
cout << "小猫叫" << endl;
}
};
class Dog : public Animal {
public:
void Speak() {
cout << "小狗叫" << endl;
}
};
void doSpeak(Animal& animal) {
animal.Speak();
}
void test01() {
Cat c;
doSpeak(c);
Dog d;
doSpeak(d);
}
int main() {
test01();
system("pause");
return 0;
}
动态多态满足条件:
动态多态使用:父类指针或引用 执行子类对象
原理:
纯虚函数和抽象类:
纯虚函数语法:virtual 返回值类型 函数名 (参数列表) = 0
当类中有了纯虚函数,这个类也称为抽象类
抽象类特点:
# include
# include
using namespace std;
class MakeDrunk {
public:
virtual void Boil() = 0 {};
virtual void Brew() = 0 {};
virtual void PutInCup() = 0 {};
virtual void PutSomething() = 0 {};
void Work() {
Boil();
Brew();
PutInCup();
PutSomething();
}
};
class Coffee : public MakeDrunk {
public:
virtual void Boil() {
cout << "煮沸农夫山泉" << endl;
}
virtual void Brew() {
cout << "煮咖啡" << endl;
}
virtual void PutInCup() {
cout << "放入杯中" << endl;
}
virtual void PutSomething() {
cout << "放牛奶和糖" << endl;
}
};
class Tea : public MakeDrunk {
public:
virtual void Boil() {
cout << "煮沸自来水" << endl;
}
virtual void Brew() {
cout << "煮茶" << endl;
}
virtual void PutInCup() {
cout << "放入杯中" << endl;
}
virtual void PutSomething() {
cout << "放茶叶" << endl;
}
};
void doWork(MakeDrunk* md) {
md->Work();
}
void test01() {
doWork(new Tea);
doWork(new Coffee);
}
int main() {
test01();
system("pause");
return 0;
}
虚析构和纯虚析构:
多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码
解决方式:父类中的析构函数改为虚析构和纯虚析构
虚析构和纯虚析构共性:
虚析构和纯虚析构区别:
虚析构:virtual ~类名(){}
纯虚析构:virtual ~类名() = 0
类名::~类名(){}
# include
# include
using namespace std;
class Animal {
public:
Animal() {
cout << "animal构造" << endl;
}
//virtual ~Animal() {
// cout << "animal析构" << endl;
//}
virtual ~Animal() = 0;
virtual void Speak() {
cout << "动物叫" << endl;
}
};
Animal::~Animal() {
cout << "animal析构" << endl;
}
class Cat : public Animal {
public:
Cat(string name) {
m_Name = new string(name);
cout << "cat构造" << endl;
}
~Cat() {
if (m_Name != NULL) {
cout << "cat析构" << endl;
delete m_Name;
m_Name == NULL;
}
}
void Speak() {
cout << "小猫叫" << endl;
}
string* m_Name;
};
void test01() {
Animal* a = new Cat("Tom");
a->Speak();
delete a;
}
int main() {
test01();
system("pause");
return 0;
}
总结:
对文件进行操作需要包含头文件
文件类型:
操作文件的三大类:
ofstream
:写ifstream
:读fstream
:读写写文件:
1.包含头文件
2.创建流对象
3.打开文件
4.写数据
5.关闭文件
打开方式 | 解释 |
---|---|
ios::in |
目的是读文件 |
ios::out |
目的是写文件 |
ios::ate |
初始位置:文件尾 |
ios::app |
追加方式写文件 |
ios::trunc |
文件存在先删除,再创建 |
ios::binary |
二进制 |
# include
# include
# include
using namespace std;
void test01() {
ofstream os;
os.open("test.txt", ios::out);
os << "姓名" << endl;
os << "性别" << endl;
os << "年龄" << endl;
os.close();
}
int main() {
test01();
system("pause");
return 0;
}
读文件:
# include
# include
# include
using namespace std;
void test01() {
ifstream ifs;
ifs.open("test.txt", ios::in);
if (!ifs.is_open()) {
cout << "error" << 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) {
cout << c;
}
ifs.close();
}
int main() {
test01();
system("pause");
return 0;
}
打开方式指定:ios::binary
写文件:
调用成员函数write
函数原型:ostream& write(const char * buffer, int len)
解释:buffer
->内存中一段存储空间 len
是读写的字节数
# include
# include
# include
using namespace std;
class Person {
public:
char m_Name[1024];
int m_Age;
};
void test01() {
ofstream ofs("person.txt", ios::out | ios::binary);
Person p = { "张三", 30 };
ofs.write((const char*)&p, sizeof(p));
ofs.close();
}
int main() {
test01();
system("pause");
return 0;
}
读文件:
调用成员函数read
函数原型:istream& read(char * buffer, int len)
解释:buffer
->内存中一段存储空间 len
是读写的字节数
# include
# include
# include
using namespace std;
class Person {
public:
char m_Name[1024];
int m_Age;
};
void test01() {
ifstream ifs("person.txt", ios::in | ios::binary);
if (!ifs.is_open()) {
cout << "error" << endl;
return;
}
Person p;
ifs.read((char*)&p, sizeof(Person));
cout << p.m_Name << p.m_Age << endl;
ifs.close();
}
int main() {
test01();
system("pause");
return 0;
}