C++语法详解学习笔记

Charpter001

C++基本数据类型复习 :
    变量
    常量
    常变量 const
    字面值变量
    符号常量 #define PI 3.14 符号常量是使用预处理器指令进行定义#define
             预处理器:是编译器把C++代码编译为机器指令之前执行的一个过程
                
    
C++对数据类型的简单理解:
    整形:short int(简写为short):至少是16位,也就是2bit来存储
            int: 一般是4bit不同的系统不同,有些是2bit,所以对于无符号数用4bit来存储最大表示范围为0-65535,对于有符号数表示的范围为-32768-32767
            long int(简写为long):一般为8bit,至少4bit(不同的系统不一样)
            long long
            {sizeof(int):4,sizeof(long):8}
            最大值和最小值的表示:#include<climits> INT_MAX,INT_MIN,SHORT_MAX,SHORT_MIN
            
    字符型:char
            转义字符:\n,\b,\\(在windows中的系统文件中经常使用)
    浮点数:float
            double
            long double
    布尔型:bool
    复合类型:枚举类型 enum
                数组类型 
                结构体类型(结构体名表示相应的数据类型)
                类类型
    其他类型:
            指针类型
            引用类型
            空类型

Charpter002

变量的声明类型:
    [存储类区分符|类型限定词]<类型区分符>声明符
    存储类区分符:extern,static,auto,register,typedef
    类型限定符:const,
    类型区分符:int, double,float等
    extern const int* p;
    如果不是指针:前三者的顺序是无关紧要的;
    
声明的规则和限制:
    函数的返回值不能是一个函数,但是可以是一个函数指针 return int(*funcName())()
    函数返回值不能是一个数组,但可以是一个数组指针和数组名 return array
变量的赋值和复制初始化:
    赋值是变量在已经有值得基础上进行原变量的擦除,新变量的写入
    复制初始化是在初始化变量的时候对变量进行赋值 int a=2(复制初始化)
    直接初始化 int a(2);
复杂变量的声明:
    1:复杂变量的声明,复杂的原因主要是*,[],()这三种运算符的作用,*表示指向变量的指针,()表示返回类型为XXX的函数,[]表示XXX的数组
    2:*是前缀运算符,[],()是后缀运算符,前缀运算符只能出现在标识符的后面 int[22]a,int b*,int*[]c,int*[]f()都是错误的
    3:[],()优先级比*高 int (*b)[] 表示b指针指向一个数组 int (*b)()表示b指针指向一个函数
        int*(*b)() 标志该指针指向一个返回类型为int*的函数
        int* b[]:[]优先级更高,所以b是一个数组,数组中的每一个元素是int*
    4:typedef的使用详解:
        typedef int c;表示c是int的别名,在后续中int和c是等级的
        typedef int* c[10];表示c是一个由10个int类型的指针构成的数组,后续中c p;表示p就是10个int类型的指针构成的数组
        
    [ ],()的优先级比*来的高;
数组指针和指针数组:
    数组指针:强调的是指针,int (*p)[10] p是一个指针,指向的是一个数组
    指针数组:int *p[10],数组中的每一个元素都是指针 p表示一个二级指针
    
    举个例子:
        int (*p)[4]; int a[4]={0},int b[33][4]={0};int c[5]={0}
        
        p=&a;正确 p=a错误,a是指针,而p是地址值;
        p=&b[0];正确,p=&b[1]正确,p=&b错误,b是指向二维数组的指针
        p=&c;错误,c的数组的大小和p不同,表示相应的内存分配空间不同;
        
        读取元素:*p[0],*p[1]表示读取相应的内容;

Charpter003

指针类型:
    基本的不再复习
    
    空指针:空指针有指向,但是它指向的地址是特殊的,
            该地址不允许存放数据和不允许程序访问,
            所以空指针不能操作该地址里的东西,
            我们就理解为“指针指向了空,无法操作了”
            空指针在头文件中的宏定义中定义了相关的类型 (void*)0
    void* 指针
            类型为void的指针,表示无类型指针,这种指针可以保存任何类型对象的地址
            int* pint;
            void* pvoid;
            1:pvoid可以被赋值为pint pvoid=pint;
            2:pint不能赋值为pvoid,如果一定要强制转换 pvoid=(int*) pint;
            
            
C++中的内存划分和动态分配内存的关键字:
    C++将内存划分为堆,栈,自由存储区,全局/静态存储区,常量存储区
    栈特点:
        栈存储的是自动变量
        栈中的内存的分配与释放是有编译器自动完成,不需要手工操作
        栈内存的分配只涉及一个指针的递增
        使用栈分配的内存容量非常有限,一般只有几M的容量
    堆和自由存储区都是C++中的动态存储区域:
        使用new,delete进行动态分配内存和释放 在自由存储区分配
        new deletez在创建时自动执行构造函数,在消亡时要自动执行析构函数;
        malloc,free是在堆中分配内存
        使用malloc时返回的是void*类型的数据,所以需要进行强制转换;
        使用malloc时需要计算分配内存空间的长度;
        
        堆是动态分配的内存,只有在运行的时候才分配内存
        堆中内存的释放需要程序员自己释放
        可以在堆中分配任意的内存块
        堆的存储空间大
    全局变量区和静态存储区:
        全局变量和静态变量被分配到该内存中
    常量存储区:
    
C++中static的作用主要有两种:
    第一个限定作用域 第二个作用是保持变量内容的持久化
    C语言中的用法:
        1:全局静态变量:
            用法在全局变量上加上static,全局变量就定义成一个全局静态变量, static int temp;
            内存中的位置:静态存储区,在整个程序的运行期间一直存在
            全局静态变量在声明他的文件之外是不可见的,准确的说是从定义处开始到文件结尾
        2:局部静态变量:
            在局部变量之前加上关键字static,局部变量就变成了一个局部静态变量。
            内存中的位置:静态存储区,在整个程序的运行期间一直存在
        
    
    C++中的用法:
        1:类的静态成员:
            class A{
                private:
                    static int val;
            };
            在C++中必须对他进行初始化,初始化时使用作用域运算符来标明他所属类,其属于该类的所有成员共有,只有一个copy
        2:类的静态成员函数:
            class A{

              private:

                static int func(int x);

          };
            (静态成员函数只能范围静态的成员变量,不能访问私有变量)
           实现的时候也不需要static的修饰,因为static是声明性关键字;
            类的静态函数是该类的范畴内的全局函数,不能访问类的私有成员,只能访问类的静态成员,不需要类的实例即可调用;
            实际上,他就是增加了类的访问权限的全局函数;
            静态成员函数可以继承和覆盖,但无法是虚函数;

Charpter004

C++中的函数的使用:
    1:基本不再介绍
    2:C++中函数的返回类型不能使函数或者是数组类型,但是可以使指针;
    3:C++中指针数据类型,形参
C++中的指针,引用和值传递引用
    1:形参中使用数组指针来进行传递参数 比如 f(int (*a)[10])和传递f(int a[][4])这种是类似的
    2:一维数组中的参数传递:void f(int *a)// void f(int a[]){使用这种方式防止数组越界一般需要传递数组的长度参数}//void f(int a[11])都是可以的
    3:多维数组,比如说是三维数组,传递参数 void f(int(*a)[10][5])
    4:引用传递就是对象的别名
    
C++中的函数修饰符:
    内联函数;extern修饰的函数;
    
C++中函数重载:
    C++中按照函数的参数分,可以分为函数重载,覆盖和函数隐藏;
    函数重载:是在同一类域内,函数名相同,但是函数参数不同的函数
    函数覆盖:
    函数隐藏:
    
C++中将函数写在多个文件中:
    C++中的文件可以分为源文件和头文件等
    头文件一般包含类,函数,变量的声明,没有实现
    源文件中一般是对函数,类,变量的定义;将头文件引用进当前的源文件中#include "...",#include<iostream>:表示从标准库中引入相应的头文件
    在源文件中使用#ifndef来解决包含头文件多次的问题,也就是函数预处理;

Charpter005

C++中的面向对象:
    继承通过:来进行继承相应的父类,用virtual来实现多态内容
    C++中通过public,prvate,protected三个关键字来实现信息的隐藏;
    
C++中的成员函数,成员变量等;
C++构造函数,复制构造函数,析构函数;
C++构造函数:
    构造函数可以有形参也可以没有形参;还可以重载多个构造函数的版本
    构造函数不能是const类型修饰
    创建对象就要自动执行一个构造函数
    默认构造函数,如果是创建了一个构造函数系统就不再自动创建默认构造函数;
C++析构函数:
    析构函数是用来释放或者返还生命周期即将结束的类对象所占据的资源
    默认析构函数:若没有显式定义析构函数,系统会自动为类添加一个默认的析构函数
    若自己定义了析构函数,默认的析构函数还是存在的,这一点与构造函数是不同的;
    
C++对象初始化:
    为什么要进行初始化,原因就是在创建类的时候不能进行初始化,
    因为在定义类是编译器不会为类分配存储空间,
    这就意味着对于类中的数据成员,创建类时不能进行初始化,因为没有空间来存储这些数据
    class A{ int i=0;} ERROR:不能进行初始化;
    
    成员初始化和构造初始化的区别:
        成员初始化才是真正的成员初始化,构造初始化其实是赋值操作;
        必须使用和不能使用成员初始化:
            必须使用成员初始化:
            没有默认构造函数的对象成员,const成员,引用类型的成员
                没有默认构造函数的成员对象;
                class B{
                public:
                    B(int i){}
                }
                class A{
                public:
                    B mb;
                    A(){
                        mb=B(3); 出错因为B mb的过程先于A()
                    }
                }
                
                class A{
                puubic:
                    B mb;
                    A():mb(3){}
                }
                
                const成员:const对象是无法进行赋值操作的,也就是说
                class A{
                public:
                    const int a;
                    A(int i){
                        a=i;//出错
                    }
                }
                正确方式
                class A{
                public:
                    const int a;
                    A(int i):a(i){}
                }
        数组成员不能在成员初始化中进行初始化
        不能使用成员初始化初始化静态成员static
            
C++复制构造函数:
        复制构造函数,直接初始化,复制初始化
        
    复制构造函数的作用:对对象进行初始化,一般是把一个已存在的对象复制到新创建的对象中时会使用复制构造函数;
    A ma; A ma1(ma);此时会调用复制构造函数;
    A ma; A ma1=ma;此时也会调用复制构造函数;
    A ma(实参);此时会调用直接初始化函数;
    
    赋值和复制的区别:赋值是在两个已经存在的对象之间进行
    A ma1; A ma2; ma1=ma2;赋值初始化
    A ma1; A ma2(ma1);复制构造函数
    A ma(实参);直接初始化;

Charpter006

名称空间基础:
    名称空间,提供一个声明名称的区域,一个名称空间中的名称不会与另一个名称空间中相同的名称发生冲突;
    
    namespace N{...}名称空间不可以只声明不定义,也就是是一个namespace必须要有{}部分
    嵌套名称空间:namespace M{
        namespace N{int a=1;}
    }
    cout<<M::N::a<<endl;
    
C++中类中的成员专题:
    静态成员:
    class A{
        static int a;//静态成员变量
    }
    静态数据成员属于整个类,而不是属于某个对象;
        1:静态数据成员被类中的所有的对象共享,每个类对象都只有静态数据成员一份共同的副本
           如果静态成员数据发生了变化,那么对于所有的对象中的静态成员数据都发生可变化
        2:类名或者使用对象名来调用相应的静态成员变量;
        3:创建对象只会为对象的非静态成员分配内存空间;而不会为静态成员变量分配内存;
        
    静态成员变量的初始化:
        1:静态成员变量时在定义时进行初始化,定义时默认的值为0;
        2: 静态数据成员不能使用构造函数初始化;
        class A{
            public:
            static int a;
            A(int b){
                a=b;//ERROR出错
            }
        }
        静态成员变量必须在类外进行定义
        3:静态数据成员也不能在成员初始化列表中初始化;
        
    静态成员函数:
        class A{
        pubic:
            static void funcName(int an,int b){
            ...
            }
        }
        1:静态成员函数属于这个类,所有的对象都有这个静态成员函数的一副本;
        2:静态成员函数没有this指针
        3:静态成员函数只能访问这个类的其他静态成员(必要条件,否则不知道具体访问的是什么成员变量)

Charpter007

//C++中的继承:
    子类中的成员变量:
        一部分是从父类继承的成员(非静态)
        一部分是自己新增加的成员(非静态)
    静态成员,继承和友元:
        不管静态成员被继承多少次,静态成员也只会有一个,静态成员是属于整个类的
    父类中的构造函数,复制构造函数,析构函数,赋值操作符函数不会被子类继承;
        所以在子类创建构造函数进行初始化时,如果需要调用父类的构造函数,
        此时构造函数的调用顺序,首先是调用父类构造函数,然后调用子类的构造函数,析构函数释放时的顺序恰好相反;
        调用的方式有两种:一种是显示调用,一种是隐式调用;
        显示调用就是使用在子类中使用列表初始化的方式进行初始化成员变量的操作
            class A{
                public:
                    int a;
                A(int b):a(b){}
            }
            class B:public A{
                public:
                    int c;
                    int age;
                    B(int a,int j,int m):A(j),c(j),age(m){}
            }
            
        隐式调用的方式:
            如果父类中没有默认的构造函数,必须通过显示方式初始化;(就像刚才的例子)

//C++继承中的动态类型和静态类型:
    静态类型值得是对象在声明时的类型;
        这种类型在编译阶段就能确定,静态类型在程序与运行阶段不会改变;
    动态类型指的是当前对象实际指向的类型:
        这种类型需要在运行时被确定;
    A为父类:A *pa 静态类型,在编译阶段能够确定
            但是pa指向的类型是无法确定的,所以需要在动态运行阶段才能确定;
            B为子类, A *pa=&mb,pa为静态类型,mb为动态类型;
            将子类对象赋给父类对象时,会把子类的父类部分切除,然后把切除部分赋给父类对象;
            
    C++中通过动态绑定的方式实现多态;
    必须通过指针或者引用方式实现多态方式;A *pa=new B() A *pa=&mb;
    虚函数:虚函数的底层是实现,虚析构函数,抽象基类等;
    虚析构函数:delete pa时只有父类的构造函数被释放,子类空间没有释放,所以就需要引入相应的虚析构函数;

Charpter008

虚函数的底层实现内容

猜你喜欢

转载自blog.csdn.net/hufanglei007/article/details/81778724