【总结】C++总结!!!

来源:互联网 发布:mac白屏很久 编辑:程序博客网 时间:2024/04/30 11:03
基础:
1、C/C++的不同点
  • 关键字:C++98----->63
  • 文件后缀.c/.cpp
  • 源文件--->工程不同----->编译器不同--->语法不同
  • 函数----->默认类型:C里面默认int,C++没有默认
                              参数列表:C语言--->没有参数:可传可不传
                                          C++----->没有参数:传参会报错,但是C++支持缺省参数
        注:缺省参数一般放在函数的声明位置,不可以在声明和定义的地方同时出现缺省值。
2、函数重载(静态多态):
        概念:在同一作用域内,含有几个函数名相同,参数列表不同(参数的个数、类型、次序),与返回值无关的函数。
3、明名空间:解决明名冲突的问题。
                      没有名称的明名空间只能够在当前文件使用(文件作用域)。
4、对象模型:对象中各个成员在内存里面的布局。
                    对象里面的成员函数、static成员存储在对象的公共存储区
                    对象的成员变量存储在自己的空间里面。
5、编译器是如何识别一个类的?
                    1、识别类名----->2、识别类里面的成员变量----->识别类中的成员函数和static成员函数的重写(成员函数参列表还原this,改写成员函数体,非静态成员+this)。
6、this指针总结
  • this指针类型:类类型*const
  • this指针只能在非静态成员函数体内使用
  • 编译器自动传递---->
进阶:
1、类里面的六大默认成员函数:
构造函数:
  • 概念:构造函数是已个特殊的函数,名字和类名相同,创建类类型对象的时候有编译器自己调用。在对象的生命周期内只调用一次,以保证每个数据都有一个合适的初始值。
性质:
  •  1、名称和类名相同
  •  2、没有返回值
  •  3、有初始化列表(可以没有)
  •  4、对象被创建的时候有编译器自己调用,在对象生命周期内只调用一次。
  •  5、构造函数可以重载,实参决定调用的构造函数。
  •  6、如果没有显示的定义构造函数,当编译器感觉需要的时候会自己提供一个默认的构造函数。
  •  7、无参构造函数和带有缺省值的构造函数都称为是构造函数。而且缺省构造函数是能含有一个。
  •  8、构造函数不能使用const来修饰?
           解:构造函数是初始化成员的,const修饰的是this指针,当被const修饰的时候就无法更改,即无法初始化
初始化列表
  • 类里面的成员变量(非静态)只能在初始化列表里面出现一次,
  • 不能再初始化列表里面出现this指针---->this指针是通过对象来调用的,在构造函数里面,对象并没有构造完整
  • 初始化的顺序只和成员在类里面的声明顺序有关
  • const修饰成员,类类型对象,引用类型必须在初始化列表里面初始化
什么情况下编译器合成构造函数?
  • 类和对象---->将对象和成员构造完整
  • 继承体系---->将基类构造完整
  • 虚拟继承----->push 1---填写偏移量表格地址
  • 带虚函数类构造对象---->填写虚表指针
拷贝构造函数
概念:在创建对象的时候用已经存在的同类型的对象来初始化的一类特殊的构造函数。
参数要求:
  1. 单个参数
  2. 参数为类类型的引用
特征:
  1. 构造函数的重载
  2. 参数必须是类类型的引用
  3. 如果没有显示定义系统会自己合成一个默认的拷贝构造函数。
注:如果拷贝构造函数的参数不是类类型对象的引用会怎样?
        解:如果参数直接是类类型的对象,那么在函数传参的时候就会拷贝构造一份参数对象,那么就会调用拷贝构造函数,这样一直调用拷贝构造               函数,并且这个拷贝构造函数是没有终止条件的。
运算符重载
概念:是一类特殊的函数,将同类型的对象作为参数来对自己进行赋值,返回值为该对象的引用的特殊函数。
  • 前置++和后置++的区别?        

 返回值参数前置++对象的引用无后置++返回对象的值int
三类重载输出运算符:
  • 1、成员函数----->含有缺陷,调用的时候只能 t<<cout;
  • 2、普通函数----->不能再类外面访问类内的private成员
  • 3、友元函数(推荐)----->返回值是输出流对象引用,参数为输出流对象引用和需要输出对象引用。
需要成对重载的符号:
  • 重载[],T* operator[]()和const T* operator[]()const
  • 重载!=和==
析构函数
概念:析构函数是在对象被销毁的时候由编译器自己调用,完成一些资源清理和汕尾工作的特殊函数
特性:
  • 函数名在类型名前面加上~
  • 由编译器自己调用
  • 不能含有参数
  • 没有返回值
  • 一个类里面只能够含有一个析构函数
  • 析构函数并不是删除对象、而是做一些清理工作
动态内存管理
  • new
    •  申请空间:void* operator new(size_t size)--->malloc
    • 调用构造函数(选择)              
  • delete
    • 调用析构函数(选择)
    • 释放空间---->operator delete()---->free
  • new[]
    • 申请空间---->operator new[](size_t size)---->operator new---->malloc
    • 调用N次构造函数
  • delete[]
    • 从空间前4个字节取出N,析构N次对象中的资源
    • 释放空间----->operator delete[]  (前偏4个字节)----->operator delete ---->free
继承
  • 概念:在原有类 的基础上增加和扩展其功能的一种机制。
  • 优点:增加代码的复用率,实现多态
  • 继承权限和访问权限:public、private、protect
  • 在继承体系里面基类和派生类的构造和析构函数的调用次序:
    • 构造函数:派生类构造函数参数列表---->基类构造函数----->基类对象构造函数---->派生类构造函数体
    • 析构函数:派生类析构函数----->派生类包含对象析构函数------>基类析构函数

注:在继承里面,派生类的构造需要先调用基类的构造函数对基类部分构造好,然后在调用派生类的构造函数对派生类的部分进行构造

赋值兼容规则   public
  1. 基类的指针可以指向派生类
  2. 派生类指针不可以指向基类
  3. 派生类可以给基类赋值
  4. 基类不可以给派生类赋值
基类里面的哪些函数被继承了?
           解:构造&拷贝构造&析构&赋值运算符重载
  • 同名隐藏:
    • 在继承体系里面基类和派生类含有相同名称的成员,当使用派生类对象调用的时候会优先调用派生类的同名成员
    • 和成员变量的类型无关,也和成员函数的原型无关
不同继承体系里面的对象模型
  • 单继承
            
  • 多继承
  • 菱形继承
注:在菱形继承里面存在着二义性问题
  • 虚拟继承
菱形虚拟继承的对象模型:
偏移量表里面含有两个值----->相对于自己的偏移量和相对基类的偏移量
偏移量表的模型:
注:使用虚拟继承,必须是在单继承里面才可以使用。
多态
  • 概念:
  • 分类:静态多态和动态多态
    • 静态多态包括:函数重载和泛型编程(在程序编译期间确定类型)
    • 动态多态:虚函数实现(在函数运行时候确定调用函数的类型)
  • 实现多态的条件:
    • 在继承体系里面,基类必须包含虚函数
    • 在派生类里面对基类里面的虚函数进行重写
    • 通过基类的指针或者引用来调用
注:重写:在继承体系中,基类包含虚函数,如果在派生类里面包含和基类里面的虚函数类型完全相同的函数,那么在派生类的虚表里面在相同的位置替换基类的虚函数。
  • 纯虚函数:在虚函数的后面加上=0;含有纯虚函数的类被称为抽象类----->抽象类是不可以实例化出对象的。
  • 动态多态的实现机理
    • 基类指针或者引用----->查询虚表----->调用函数
  • 带虚函数的菱形虚拟继承的对象模型
总结:
  • 派生类重写基类的虚函数实现多态,要求函数名、参数列表、返回值完全相同(协变和析构函数除外)
  • 基类中定义了虚函数,在派生类中该函数始终保持虚函数的特性
  • 只有类的非静态成员函数才能够定义成虚函数,静态成员函数不能定义成函数(虚函数是通过对象来调用的)
  • 如果在类外定义虚函数,只有在声明函数时加上virtual关键字,定义时不用加
  • 构造函数不能定义成虚函数,虽然可以将operator=函数定义成虚函数,但是建议不要定义成虚函数,容易产生混淆
  • 不要在构造函数和析构函数里面调用虚函数,在析构函数和构造函数里面,对象是不完整的,可能会出现未定义的行为
  • 最好将基类的析构函数定义成虚函数
  • 虚表是所有类对象共有的



问题:
  • 为什么将构造函数定义成虚函数?
        解:调用虚函数需要利用对象的地址来寻找虚表指针,但是在构造函数调用之前,对象是不存在的,所以不能够将构造函数定义成虚函数。
  • 为什么需要将析构函数定义成虚函数?不定义成虚函数会出现什么?
        解:在继承体系里面,假如基类的析构函数没有定义成虚函数,那么在使用基类来销毁这个派生类的时候就会直销会基类的部分,而派生类部分没有销毁。
  • 静态成员函数能否作为虚函数?
        解:不能 ,,虚函数通过虚表指针和虚表来完成调用,并且只能通过this指针来调用虚函数,那么在静态成员函数里面不存在this,显然就不能将静态成员函数定于成虚函数。
  • 友元函数能否定义成虚函数?
        解:不能,,友元函数并不是类的成员函数,那么就无法通过this来调用,即不能够将友元函数定义成虚函数。
原创粉丝点击