• C++基础复习


    1.Object-C也是面向对象的语言;
    2.#include<iostream> //#include是一个预处理指令
    3.using namespace std; //std是命名空间,using决定了该源程序中的代码可以不用指定命名空间名为std
    4.const 常量只能读,不能修改,并且定义时必须初始化;
    5.由低精度向高精度转化不会影响精度,由高精度向低精度转化会影响精度;
    函数重载:函数名相同,函数的参数不同,通过参数的判断,调用不同的同名函数,实现函数的功能;
    所以函数重载中,进行函数调用时是由实参转化为形参是按从低精度向高精度转化的;
    6.函数默认参数:默认参数的定义顺序为自右向左,即一个参数设定了缺省值(默认值)时,其右边的参数必须都要有缺省值;
    默认参数函数调用时,遵循函数调用顺序,自左向右逐个匹配。
    7.引用:
    例如:
    int a;
    int &ra = a;
    声明引用时必须同时对其进行初始化;
    不能创建一个指向引用的指针;
    不能声明一个数组的引用;
    引用作为形参:在内存中不会产生实参的副本,它是直接对实参进行操作的。 //使用引用传递参数,节省了空间
    8.常引用:
    int a;
    const int &ra = a;
    ra = 1;//错误,没有权限
    a = 1;//正确
    定义函数:void f(const int &ra); //保证在函数内部,ra的值不会被改变
    9.函数形参与调用时实参的关系:

        在调用函数运行时,才将实参赋值给形参。
    10.类的访问限制:
    private : 默认类型 //只能被本类的成员函数使用。
    public
    protected
    11.类:
    成员函数实现放在类的定义中,则默认为内联函数;//是一种建议,不是绝对的就当做内联函数。
    函数实现放在类外,可加inline关键字定义为内联函数。
    如: inline void Cloack::showClock(){cout<<"I am clock!"<<endl;}

    每个类的对象都有一份自己的数据空间,但是类的成员函数只存储一份,为所有的对象所共有。
    类的成员函数中可以访问本类对象的私有成员。
    12.构造函数与析构函数:
    构造函数:为对象申请空间以及初始化赋值。 ///////
    //具有初始化列表的构造函数:Clock(int h,int m,int s): hour(h),minute(m){second=s;}
    写在初始化列表与函数体中的区别为:写在初始化列表中认为:简单变量的定义并初始化
    写在函数体中:简单变量的先定义再赋值;故前者效率较高。
    13.析构函数与构造函数的执行顺序是相反的。析构函数严格按照此相反顺序执行!!应该是压栈处理的缘故。
    派生类类的构造函数在定义对象时调用,顺序为先是基类的构造函数,然后是类内部对象成员的构造函数,最后是该派生类本身的构造函数。
    14.拷贝构造函数分为浅拷贝与深拷贝。
    浅拷贝只是复制对象空间,而深拷贝将复制对象空间以及之外申请的额外资源(一般是堆空间)。
    浅拷贝会出现析构时的错误。可能会对同一个内存资源进行两次释放删除,导致错误的出现。
    拷贝构造的参数必须是类对象的引用,否则会造成拷贝构造函数的递归调用。因为不使用引用,在调用时,首先将实参copy给形参,//此时会调用拷贝构造函数(形成递归)然后再对形参进行操作。最后形成对拷贝构造函数递归的调用。最好使用const类型的表示引用的形参。--》考虑实参是怎么向形参传递值得??

    另外:

    赋值运算符和复制构造函数都是用已存在的B对象来创建另一个对象A。不同之处在于:赋值运算符处理两个已有对象,即赋值前B应该是存在的;复制构造函数是生成一个全新的对象,即调用复制构造函数之前A不存在。
    CTemp a(b); //复制构造函数,C++风格的初始化
    CTemp a=b; //仍然是复制构造函数,不过这种风格只是为了与C兼容,与上面的效果一样
    在这之前a不存在,或者说还未构造好。

    CTemp a;
    a=b; //赋值运算符
    在这之前a已经通过默认构造函数构造完成。


    15.每个非静态的成员函数均有一个隐含的指针变量this。//是一个指针,表示对象的地址。
    16.类的静态数据成员,只有一份,存储在全局区。所有的对象共享该静态数据成员。
    类的静态数据成员,必须在类外进行初始化。它的生命周期是与类相同的,不依赖于对象的存在而存在。
    17.sizeof(数组名):数组名本身是一个地址常量。
    以 char arr[10];为例
    则 数组名 的类型为:char * const //是一个地址常量
    其另一个语义是:数组对象。 所以对数组名取地址,意思即是对数组对象取地址,其结果的值就是数组名本身的地址常量值。
    所以不能说数组名是一个指针。
    当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。
    18.静态成员函数只能访问静态成员数据或静态成员函数,不能访问非静态、的成员函数或成员数据。
    其不具有this指针,又是所有对象共享的,又没有this指针,所以其只能访问静态的成员数据或者成员函数。

    其他成员函数具有this指针,用来区分参数对象成员和本身对象成员。(静态的成员是共有的,不需要区分不同的对象,所以就没有this指针)
    19.const数据成员,其必须在构造函数的初始化列表中列出,以对其进行初始化。//因为const类型常量进行定义的时候必须初始化。
    const成员函数不能调用非const函数,但是能够使用非const得成员数据,只要不修改它就行。
    20.友元函数,可以是非成员函数。能够访问类的私有、保护、公有的成员数据。(但是通过对象名进行访问)
    友元类:类中的所有成员函数均是另一个类的友元函数。
    关于类与对象的空间分配问题!
    21.注意重载流插入运算符<<的方法:应该将运算符重载函数写为非成员函数,例如:友元函数
    ostream& operator <<(ostream& out,const 类名& a); //注意返回值为 ostream 的类型。
    目的是能够使 cout<<a<<b<<endl; //正常的连续输出。
    22.函数返回引用时,返回的不能是临时变量,必须是全局变量。因为返回临时变量,释放了的时候,引用所指向的就是空了。

    关于前置与后置自增运算符重载的区别:http://blog.csdn.net/randyjiawenjie/article/details/6747720


    继承:

    保护成员与私有成员的区别体现在继承上。

    继承分为:公有继承,私有继承,保护继承。
           公有继承,基类的公有成员和保护成员作为派生类的公有成员,外部可以访问;
           私有继承,基类的公有成员和保护成员作为派生类的私有成员,外部不可以访问;
           保护继承,基类的公有成员和保护成员作为派生类的保护成员,外部不可以访问;


    23.派生类的构造函数:
    派生类不继承基类的构造函数与析构函数。故,需要自己添加相应基类的构造函数。
    当派生类中有对象成员时,其构造函数的初始化列表中应该有对对象成员的初始化。此时构造函数的顺序为:先是基类,然后是对象成员,最后是
    自身。
    多重继承:构造函数顺序为派生类对基类的继承顺序。
    24.派生类的析构函数:
    继承与多重继承的析构函数,严格的与构造函数的执行顺序是相反的。
    25.基类与子类中数据成员同名进行访问,会出现二义性。
    方法:用类名限定符, 类名::成员名
    26.虚基类:
    多重继承,如果2个父类有共同的基类。则会对基类进行两次的构造。一个父类一次,造成空间的开销。浪费了对象的空间。
    虚基类:在派生类继承基类时定义。 使内存中只建立基类的一个副本。
    calss 派生类名: virtual [继承方式] 基类名
    基类的构造函数也只会在最后的派生类中继承一次。
    27.派生类能够赋值给基类,反之则不可以。赋值后基类的类型还是基类,只能使用基类的成员数据与成员函数。

    28.关于创建对象的两种方法:使用new 与 不使用new,有一定的区别。使用 new 进行创建时,应该用delete释放空间。只有使用delete时
    才会调用析构函数对对象进行析构。且使用new时,如果创建的对象是一个无参数的对象,那么所new的类名的后边也应该加上括号,但是直接
    定义对象,就不需要加括号。
    例如:对于类Student 则应该为; Student * pstu = new Student(); // Student stu;

    多态: 关键词:虚函数 抽象类 纯虚函数
    29.多态分为静态多态与动态多态。
    静态多态指程序编译时系统就能确定是哪个函数。 通过函数重载来实现。
    动态多态是指程序运行时系统才能确定运行的是哪个函数。动态多态是通过虚函数(virtual function)实现的。
    29.虚函数:
    虚函数的作用是:允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或者基类引用来访问这个同名函数。
    虚函数:系统会根据运行时对象所属的类来寻找与之匹配的函数。
    关联:分为了静态关联和动态关联。
    虚函数具有继承性,即在基类中将函数声明为虚函数后,无论在继承类中进行重写时是否将函数声明为虚函数,该函数均是虚函数。
    虚函数调用时应通过基类的指针或者引用进行调用。
    30.虚析构函数:
    将基类的析构函数写成虚函数。其作用是,当用基类的指针或者引用来删除派生类时,能够调用派生类的析构函数。否则只是调用基类的
    析构函数。
    但是不能将构造函数写为虚函数。 // 原因是,写成虚函数的目的是实现动态绑定,即是在运行的时候使函数与对象的类型进行绑定,来判断
    该函数是否执行,以及按何种方式执行。而在运行构造函数时,对象还没有生成,此时,无法实现动态绑定。所以构造函数不能写为虚函数,
    构造函数内部也不能调用虚函数。
    31.纯虚函数:
    没有函数体,起作用就是为其派生类保留一个函数的名字,以便派生类对它的行为进行重新定义。
    virtual 函数类型 函数名(参数列表) = 0;
    32.抽象类:
    含有纯虚函数的类为抽象类。抽象类只能作为基类,无法进行实例化,即不能创建一个抽象类的对象,但是可以声明一个抽象类的指针和引用。

    面向对象的三大特征:封装(encapsulation)、继承(inheritance)、多态(polymorphism)。
    模板:
    33.函数模板:函数模板被调用时编译器才产生代码。 用实参的类型替换掉形参类型,这个过程叫做函数模板的实例化。
    template<class T>
    T min(T a,T b)
    {
    return (a<b)?a:b;
    }
    34.函数模板的特化:使模板能够处理一种特殊情况下的问题。
    template<> 返回类型 函数名(参数列表)
    {函数体}
    35.类模板:
    类模板的的实例化,在程序中显式的指出。
    类模板只有实例化后才能产生具体的代码。
    特化类模板:必须在前面加上 template <>

    //或许你也可以说,你所面临的这一切都不是问题。

    其他问题:

    sizeof 求一个空类的结果为1。

    原因为:所谓类的实例化就是在内存中分配一块地址,每个实例在内存中都有独一无二的地址。同样空类也会被实例化,所以编译器会给空类隐含的添加一个字节,这样空类实例化之后就有了独一无二的地址了。所以空类的sizeof为1。C++编译器不允许对象为零长度。试想一个长度为0的对象在内存中怎么存放?怎么获取它的地址?为了避免这种情况,C++强制给这种类插入一个缺省成员,长度为1。如果有自定义的变量,变量将取代这个缺省成员。 

  • 相关阅读:
    locust与jmeter在压测时的比较
    通过python异步通讯方式构建高并发压力测试工具
    开博寄语
    【linux】【root权限的掌控】
    【linux】【qt5界面】【系统托盘图标的实现】
    【win】【qt5】【本地网络相关信息,诸如ip,mac等】
    【win】【qt5】【qt汉化:输入框之右键英文变中文】
    【linux】【qt5】【qt程序防多开设置,通过设置共享内存实现,超短代码,超级有效】
    【qt】【QString的诸多操作】
    【linux】【qt5】【将linux下的qt程序打包发布(完全适用于中标麒麟)】
  • 原文地址:https://www.cnblogs.com/rickhsg/p/3720810.html
Copyright © 2020-2023  润新知