C++核心编程
内存四区
- 代码区:存放函数体的二进制代码,由OS管理
- 全局区:存放全局变量、静态变量、常量 (局部变量和局部常量不在)
- 栈区:由编译器自动分配释放,存放函数参数值、局部变量等 (不要return局部变量的地址和引用)
- 堆区:由程序员分配和释放,若程序员不释放,程序结束时由OS回收 (利用new可以将数据开辟到堆区,如int *p = new int(10);)
new和delete操作符
#include <iostream>
using namespace std;
int *func(){
//在堆区创建整型数据
//new返回的是该数据类型的指针
int *p = new int (10);
return p;
//在堆区创建数组
int *arr = new int[10];
delete[] arr;
}
int main(){
int *p = func();
cout << *p << endl;
cout << *p << endl;
//释放堆区数据
delete p;
}
引用
//引用:给变量起别名 ,因此对别名的值(原名的值)修改就是对原名的值(别名的值)修改
#include <iostream>
using namespace std;
int main(){
int a = 10;
int &b = a; //引用要初始化,且一旦初始化就不可改变
cout << a << ' ' << b << endl; //10 10
b = 100;
cout << a << ' ' << b << endl; //100 100
}
//引用的本质:指针常量( * const )
函数高级
函数默认参数
//注:如果某个位置已经有了默认参数,那么从这个位置往后,从左到右都必须有默认参数
int func(int a,int b = 20,int c = 30){
return a + b + c;
}
函数占位参数
void func(int a,int){
cout << "Hello World" << endl;
}
int main(){
func(10,10);
}
函数重载
函数重载满足条件:
- 同一个作用域下
- 函数名称相同
- 函数参数类型不同或者个数不同或者顺序不同
类和对象
封装
访问权限:
- 公共权限:类内、类外都可以访问
- 保护权限:类内可以访问,类外不可以访问,子类可访问
- 私有权限:类内可以访问,类外不可以访问,子类不可访问
#include <iostream>
using namespace std;
#define PI 3.14
//class默认权限是private
class Circle{
//访问权限
public:
//成员变量
int m_r;
//成员方法
double calculate(){
return 2 * PI * m_r;
}
};
int main(){
Circle c1;
c1.m_r = 10;
cout << c1.calculate() << endl;
}
对象特性
构造函数和析构函数
class Person{
public:
//构造函数进行初始化操作
//无参构造函数
Person(){
cout << "Person无参构造函数的调用" << endl;
}
//有参构造函数
Person(int a){
age = a;
cout << "Person有参构造函数的调用" << endl;
}
//拷贝构造函数
Person (const Person& p){
age = p.age;
cout << "Person拷贝构造函数的调用" << endl;
}
//析构函数进行清理的操作
~Person(){
cout << "Person析构函数的调用" << endl;
}
int age;
};
int main(){
//括号法,常用
Person p1;
Person p2(10);
Person p3(p2);
}
深拷贝和浅拷贝
如果属性有在堆区开辟的,一定要提供拷贝构造函数,防止浅拷贝带来的问题
#include <iostream>
using namespace std;
class Person{
public:
//构造函数进行初始化操作
//无参构造函数
Person(){
cout << "Person无参构造函数的调用" << endl;
}
//有参构造函数
Person(int age,int height){
m_age = age;
//属性有在堆区开辟
m_height = new int(height);
cout << "Person有参构造函数的调用" << endl;
}
//拷贝构造函数
Person (const Person& p){
m_age = p.m_age;
//浅拷贝“m_height = p.m_height;”,编译器默认实现,问题:堆区内存重复释放,因为指针m_height都指向同一块堆区空间
//深拷贝在堆区新开辟一块空间,解决浅拷贝带来的问题
m_height = new int(*p.m_height);
cout << "Person拷贝构造函数的调用" << endl;
}
//析构函数进行清理的操作
~Person(){
if(m_height != NULL){
delete m_height;
m_height = NULL;
}
cout << "Person析构函数的调用" << endl;
}
int m_age;
//有智指针,则要在堆区开辟
int *m_height;
};
int main(){
Person p1(18,160);
Person p2(p1);
cout << p2.m_age << ' ' << *p2.m_height << endl;
}
静态成员函数特点
- 程序共享一个函数
- 静态成员函数只能访问静态成员变量
this指针
- this指针指向被调用的成员函数所属的对象
- *this就是该对象
- 本质是指针常量,指向不可修改
class Person{
public:
//常函数,this指针指向的值也不可以修改
void showPerson() const{
//报错this->m_A = 100;
this->m_B = 100;
}
//在常函数中不可修改
int m_A;
//在常函数中可以修改
mutable int m_B;
};
//常对象,只能调用常函数
const Person p1;
//报错p1.m_A = 100;
p1.m_B = 100;
友元
全局函数做友元
#include <iostream>
using namespace std;
class Building{
//声明好朋友
friend void goodGay(Building *building);
public:
Building(){
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
string m_SittingRoom;
private:
string m_BedRoom;
};
void goodGay(Building *building){
cout << "friend全局函数正在访问:" << building->m_SittingRoom << endl;
//好朋友访问私有变量
cout << "friend全局函数正在访问:" << building->m_BedRoom << endl;
}
void test01(){
Building building;
goodGay(&building);
}
int main(){
test01();
}
类做友元
#include <iostream>
using namespace std;
class Building{
//声明好朋友
friend class GoodGay;
public:
Building(){
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
string m_SittingRoom;
private:
string m_BedRoom;
};
class GoodGay{
public:
GoodGay(){
building = new(Building);
}
void visit(){
cout << "friend类正在访问:" << building->m_SittingRoom << endl;
cout << "friend类正在访问:" << building->m_BedRoom << endl;
}
Building *building;
};
int main(){
GoodGay gg;
gg.visit();
}
成员函数做友元
#include <iostream>
using namespace std;
class Building{
//声明好朋友
//friend void GoodGay::visit();报错,不知道原因,可能是编译器问题
friend class GoodGay;
public:
Building(){
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
string m_SittingRoom;
private:
string m_BedRoom;
};
class GoodGay{
public:
GoodGay(){
building = new(Building);
}
//类外实现成员函数,注:仍然要在类内声明;
void visit();
Building *building;
};
void GoodGay::visit(){
cout << "friend成员函数正在访问:" << building->m_SittingRoom << endl;
cout << "friend成员函数正在访问:" << building->m_BedRoom << endl;
}
int main(){
GoodGay gg;
gg.visit();
}
运算符重载
#include <iostream>
using namespace std;
class Person{
public:
Person(){
}
Person(int A,int B){
this->m_A = A;
this->m_B = B;
}
//成员函数重载+号
Person operator +(Person& p1){
Person t;
t.m_A = p1.m_A + this->m_A;
t.m_B = p1.m_B + this->m_B;
return t;
}
int m_A;
int m_B;
};
//全局函数重载+号
Person operator +(Person& p1,Person& p2){
Person t;
t.m_A = p1.m_A + p2.m_A;
t.m_B = p1.m_B + p2.m_B;
return t;
}
int main(){
Person p1(10,10);
Person p2(10,10);
Person p3 = p1.operator +(p2);
cout << p3.m_A << ' ' << p3.m_B << endl;
Person p4 = operator +(p1,p2);
cout << p4.m_A << ' ' << p4.m_B << endl;
}
继承
语法:
class 子类(派生类) : 继承方式 父类(基类){
};
#include <iostream>
using namespace std;
class Base{
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
//公共继承
class Son1: public Base{
public:
void func() {
//公共权限,类外能访问
m_A = 10;
//保护权限,类外不能访问
m_B = 10;
//报错m_C = 10;
}
};
//保护继承
class Son2: protected Base{
public:
void func() {
//保护权限,类外不能访问
m_A = 10;
//保护权限,类外不能访问
m_B = 10;
//报错m_C = 10;
}
};
//私有继承
class Son3: private Base{
public:
void func() {
//私有权限,类外不能访问
m_A = 10;
//私有权限,类外不能访问
m_B = 10;
//报错m_C = 10;
}
};
int main(){
}
多态
多态的基本使用
#include <iostream>
using namespace std;
class Animal{
public:
//虚函数
virtual void speak(){
cout << "动物在说话" << endl;
}
};
class Cat:public Animal{
public:
//子类重写父类虚函数
virtual void speak(){
cout << "小猫在说话" << endl;
}
};
class Dog:public Animal{
public:
//子类重写父类虚函数
virtual void speak(){
cout << "小狗在说话" << endl;
}
};
//父类指针或引用指向子类对象
void DoSpeak(Animal &animal){
animal.speak();
}
int main(){
Cat cat;
DoSpeak(cat);
Dog dog;
DoSpeak(dog);
}
多态实现计算器
#include <iostream>
using namespace std;
//利用多态实现计算器
//抽象类
class AbstractCalculator{
public:
//纯虚函数
//只要有一个纯虚函数,则这个类称为抽象类,抽象类无法实例化对象,且子类必须重写父类中的纯虚函数(否则子类也是抽象类)
virtual int getResult() = 0;
int m_Num1;
int m_Num2;
};
//加法类
class AddCalculator:public AbstractCalculator{
public:
virtual int getResult(){
return m_Num1 + m_Num2;
}
};
//乘法类
class MulCalculator:public AbstractCalculator{
public:
virtual int getResult(){
return m_Num1 * m_Num2;
}
};
//父类的指针指向子类对象
void Calculate(AbstractCalculator* abstractCalculator){
cout << abstractCalculator->getResult() << endl;
}
int main(){
//因为涉及到指针(地址),所以推荐在堆区开辟空间
AddCalculator* addCalculator = new AddCalculator;
addCalculator->m_Num1 = 10;
addCalculator->m_Num2 = 10;
Calculate(addCalculator);
//堆区数据手动开辟,手动释放
delete addCalculator;
MulCalculator* mulCalculator = new MulCalculator;
mulCalculator->m_Num1 = 10;
mulCalculator->m_Num2 = 10;
Calculate(mulCalculator);
delete mulCalculator;
}
//利用虚析构可以解决 父类指针释放子类对象时不干净的问题
文件操作
- ofstream:写操作
- ifstream:读操作
- fstream:读写操作
//输入输出流
#include <iostream>
//文件流
#include <fstream>
using namespace std;
#include <string>
int main(){
//创建输出文件流对象
ofstream ofs;
//打开方式
ofs.open("/users/zhangyilang/desktop/text.txt",ios::out);
//写内容
ofs << "C++爱好者" << endl;
//关闭文件
ofs.close();
//创建输入文件流对象
ifstream ifs;
ifs.open("/users/zhangyilang/desktop/text.txt",ios::in);
if(!ifs.is_open()){
cout << "文件打开失败" << endl;
}
//读数据
//第一种方式
char buf[1024] = {0};
while(ifs >> buf){
cout << buf << endl;
}
//第二种方式
string buf1;
while(getline(ifs,buf1)){
cout << buf1 << endl;
}
//第三种方式,效率低
char c;
while ((c = ifs.get() != EOF)){
cout << c;
}
}

浙公网安备 33010602011771号