【无标题】

一 程序的内存模型

1.1 内存四区

代码区

存放函数体的二进制代码,由操作系统进行管理

全局区

存放全局变量,静态变量,常量(字符串常量,const修饰的全局常量)

栈区

由编译器自动分配和释放,存放函数的参数值(形参数据),局部变量,const修饰的局部变量

不要返回局部变量的地址

int * test()
{
    int a = 10;
    return &a;
}

堆区

由程序员分配和释放

int *p = new int(10);	//在堆区创建数据,并返回其指针

1.2 new运算符

int * p = new int(10);	//创建一个堆区变量
int * arr = new int[10];	//创建一个堆区数组
delete p;	//删除变量
delete[] arr; //删除数组

二 C++中的引用

2.1 引用的基本使用

引用的作用:给变量起别名

int name = 10;
int &otherName = name;

2.2 注意事项

1.引用必须初始化

2.引用一旦初始化,就不可以更改

2.3 引用做函数参数

//地址传递
void mySwap01(int *a,int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

mySwap01(&a,&b);

//引用传递
void mySwap02(int &a,int &b)
{
    int temp = a;
    a = b;
    b = temp;
}

mySwap02(a,b);

2.4 引用做函数返回值

1.不要返回局部变量的引用

2.函数的调用可以作为左值

int& test01()
{
    int a = 10;
    return a;
}

int &ref01 = test01();	//错误,不能返回局部变量的引用

int& test02()
{
    static int a = 10;
    return a;
}

int &ref02 = test02();	//静态变量可以

test02 = 100;	//函数作为左值,将100赋值给 a

2.5 引用的本质

引用的本质是指针常量

2.6 常量引用

const int& ref = 10;	//可以直接对ref赋值为 10,并且不可以修改
void showValue(const int &value);	//防止误修改value的值

3 函数高级

3.1 函数默认参数

int func(int a,int b = 20,int c = 30)   //如果传入数据就用传入数据,否则用默认值 
{
    return a+b+c;
}

/* 注意事项
1. 如果某个位置已有了默认参数,那么从这个位置之后都必须要有默认参数
2. 函数声明和实现只能有一个有默认值
*/

3.2 函数占位参数

void func(int a,int);
void func(int a,int = 10);  //占位参数也可以有默认值

3.3 函数重载

基本语法

作用:函数名可以相同,提高复用性

满足条件:1.在同一个作用域。2.函数名相同。3.函数形参不同(类型,个数,顺序)

注意事项

  1. 引用作为重载条件

  2. 函数重载遇到默认参数

    void func(int &a);
    void func(const int &a);
    
    int a = 10;	
    func(a);	//a是变量,调用func(int &a)
    func(10);	//10 是常量,int &a = 10 不合法,而const int &a = 10 合法,调用func(const int &a)
    

四 类和对象

4.1 封装

访问权限

  1. public:类内,类外都可以访问
  2. protected:类内可以访问,可以继承
  3. private:类内可以访问,不可以继承

class与struct的区别

  1. class:默认权限为private

  2. struct:默认权限为public

4.2 对象特性

构造器和析构器

class Person
{
public:
    Person()    //构造函数,可以有参数
    {

    }

    ~Person()   //析构函数,不可以有参数
    {
        
    }
};

构造函数的分类及调用

分类:有参构造和无参构造;普通构造和拷贝构造

调用:括号法,显示法,隐式转换法

class Person
{
    int age;
    
public:
    Person()
    {
    
    }

    Person(int a)
    {

    }

    //拷贝构造:用于复制将传入对象再复制一份,用const修饰,拷贝对象与被拷贝对象类型一致
    Person(const Person &p)
    {
        age = p.age;
    }
};


void test01()
{
    //括号法
    Person p01;      //Person p() 是错误的
    Person p02(10);
    Person p03(p2);
    
    //显式法
    Person p12 = Person(10);
    Person p13 = Person(p12);
    //Perspn(10):匿名对象,当这一行执行结束后会立即释放空间
    //不能利用拷贝函数构造匿名对象,Person(p3) = Person p3;
    
    //隐式转换法
    Person p22 = 10;
    person p23 = p22;
}

拷贝构造函数调用时机

  1. 使用一个已经创建完毕的对象来初始化一个新对象
  2. 值传递的方式给函数参数传值
  3. 以值返回方式返回局部对象

构造函数调用规则

  1. 只要创建一个类,C++就会创建3个函数默认构造(空实现),有参构造(空实现),拷贝构造(值拷贝)
  2. 若写了有参构造,则编译器不再提供默认构造函数,但会提供拷贝构造函数
  3. 若写了拷贝构造函数,则编译器不再提供其他普通构造函数

深拷贝与浅拷贝(面试常问)

  1. 浅拷贝:简单的复制拷贝
  2. 深拷贝:在堆区重新申请空间,进行拷贝
m_Heigt = new int(*p.m_Heigt);

初始化列表

用途:给类中的属性进行初始化

Person() :m_A(10),m_B(20)  {}
Person(int a,int b,int c) :m_A(a),m_B(b),m_C(c)  {}

类对象作为类成员

 //Phone phone = pName  Phone phone =  Phone(pName)
 Person(string sName,string pName):m_Name(sName), phone(pName) 	//好像只能用初始化列表??
 {
 }
 string m_Name;
 Phone phone;

静态成员

静态成员变量
  1. 所有对象公用一份数据
  2. 在编译阶段分配内存(在全局区)
  3. 在类内声明,类外初始化
class Person
{
public:
    static int m_A;
private:
    static int m_B;	//静态成员变量同样有访问权限
};
//类内访问,类外声明
int Person::m_A = 10;
int Person::m_B = 100;

void test()
{
    Person p;		
    cout << p.m_A;		//静态成员变量不属于任何一个对象,因此可以 1.通过对象调用 2.通过类调用
    cout << Person::m_B;
}
静态成员函数
  1. 所有对象公用一个函数
  2. 静态成员函数只能访问静态成员变量
class Person
{
    static void func(){
        cout << m_A;
        cout << m_B;	//错误,静态成员函数只能访问静态成员变量
    }
    static int m_A;
    int m_B;
};
int Person::m_A = 10;

void test()
{
    Person p;		
    cout << p.func();		//1.通过对象调用 2.通过类调用
    cout << Person::func();
}

4.3 C++对象模型和this指针

成员变量和成员函数分开储存

  1. 只有非静态成员变量属于类的对象上
  2. 空对象占内存大小为1

this指针

  1. 解决名称冲突
  2. 返回对象本身用 *this
  3. this指针指向 被调用的成员函数 所属对象
class Person
{
public:
    Person& addPerson(Person &p)	//要返回对象的引用
    {
        this->age+= p.age;
        return *this;		//回对象本身用 *this
    }

    int age;
};

void test()
{
    //链式调用规则
    p2.addPerson(p1).addPerson(p1).addPerson(p1);
}

空指针访问成员函数

const修饰成员函数

  1. 常函数:在成员函数后加const修饰

    1. 常函数内不可以修改成员属性的值
    2. 成员属性声明时加 mutable修饰后,常函数就可以修改了
  2. 常对象:声明对象前加 const修饰

    1. 常对象只能调用常函数
class Person
{
public:
    /*
    this指针的本质相当于一个指针常量,Person * const this = p;
    函数加const修饰后相当于 const Person * const this = p;
*/
    void showPerson() const
    {
        //m_A = 100;
        m_B = 100;
    }

    int m_A;
    mutable int m_B;
};

4.4 友元

全局函数做友元

类做友元

成员函数做友元

class Building
{
    friend void friendClass(Building &b);	//用friend修饰全局函数就可以访问私有成员变量
    
private:
    int age;
};

void friendClass(Building &b){}

4.5 运算符重载

4.6 继承

基本语法

class Son : public base1, public base2 ....

继承方式

继承中的对象模型

  1. 在父类中所有的非静态的成员属性都会被子类继承下去
  2. 父类中的私有属性也会被继承,但是不可以访问

继承同名成员的处理方式

  1. 访问子类同名变量,直接访问即可
  2. 访问父类同名变量,需要加作用域
  3. 若子类中出现了与父类中同名的成员函数,则子类中的函数会屏蔽中所有的同名成员函数

继承中同名的静态成员的处理方法

void test()
{
    Son s;
    cout << s.a;    //通过调用对象的方式访问静态成员
    cout << s.Base::a;

    cout << Son::a;	//通过类直接访问静态成员
    cout << Son::Base::a;
}
  1. 访问子类同名静态变量,直接访问即可
  2. 访问父类同名静态变量,需要加作用域
  3. 若子类中出现了与父类中同名的静态成员函数,则子类中的函数会屏蔽中所有的同名静态函数

菱形继承

  1. 主要问题:在子类中继承了两份相同的数据,资源浪费,毫无意义
  2. 解决方法:虚继承

4.7 多态

多态的语法

  1. 多态的种类

    静态多态:函数重载,运算符重载,复用函数名

    动态多态:派生类和虚函数实现运行时多态

  2. 静态多态与动态多态的区别

    静态多态地址早绑定,编译阶段确定函数地址

    动态多态地址晚绑定,运行阶段确定函数地址

    class Animal
    {
        public:
        virtual void doSpeak(){}
    };
    //多态的条件
    // 1. 有继承关系
    // 2. 子类重写父类中的虚函数
    class Cat : public Animal
    {
        public:
        void doSpeak(){}
    };
    
    //多态的使用:父类的指针或引用 指向子类对象
    void test(Animal &cat)  //Animal &animal = cat;  Animal *animal = new cat;
    {
        cat.doSpeak();
    }
    

多态的原理

class AbstractCalculator
{
public:
    int num1,num2;
    virtual int getResult()		//声明虚函数
    {
        return 0;
    }

};
class addCaculator : public AbstractCalculator	
{
    public:
    int getResult()		//重写父类中的虚函数
    {
        return num1 + num2;
    }
};

void test01()
{
    AbstractCalculator *ab = new addCaculator;
    ab->getResult();	//通过指针指向子类对象
}

void test02(abstraCalculator &ab)	//通过引用指向子类对象
{	
    ab.getResult();
}

纯虚函数和抽象类

virtual void func() = 0;
//只要含有一个纯虚函数就称为抽象类
//抽象类无法实例化对象
//子类必须重写父类中的纯虚函数,否则也是抽象类

虚析构和纯虚析构

5 文件操作

  1. 文件的分类
    • 文本文件
    • 二进制文件
  2. 操作文件的三大类
    • ofstream:写文件
    • ifstream:写文件
    • fstream:读写文件

5.1 文本文件

写文件

void test01()
{
    fstream ofs;	// 1. 创建对象
    ofs.open("test.txt",ios::out);	//打开文件
    ofs << "输入想写入的内容" << endl;
    ofs.close();
}

读文件

void test01()
{
    ifstream ifs;
    ifs.open("test.txt",ios::in);

    if(!ifs.is_open())
    {
        cout << "文件打开失败" <<endl;
        return;
    }

    string buf;
    while(getline(ifs,buf)){
        cout << buf << endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值