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;
}
//利用虚析构可以解决 父类指针释放子类对象时不干净的问题

文件操作

  1. ofstream:写操作
  2. ifstream:读操作
  3. 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;
    }
}
posted @ 2022-02-21 21:40  优雅永不过时、  阅读(123)  评论(0)    收藏  举报