C++_常用总结0001

/*------------------积少成多---------------*/
http://www.cnblogs.com/lizhenghn/p/3751857.html
(1-0)命名规则:
    1、类名和函数名用大写字母开头的单词组合而成。
    2、变量和参数用小写字母开头的单词组合而成。
    3、常量全用大写的字母,用下划线分割单词。
    4、静态变量加前缀s_(表示static)。
    5、如果不得已需要全局变量,则使全局变量加前缀g_(表示global)。
    6、类的数据成员加前缀m_(表示member),这样可以避免数据成员与成员函数的参数同名。
(1)C++允许数据类型的声名语句可以出现在程序任何位置
   C++允许直接使用结构体名定义实体   //struct Demo{int a; inline int getA(){return a;};}---Demo demoT = {10};
(2)new 与 delete
    new 的书写形式:
        int *p = new int; //占4字节
        int *p = new int(10); //申请一个机器字长(4),且初始化为10
        int *p = new int[10]; //申请多个机器字长(sizeof(p) = 10*4)
    delete 的书写形式:
        delete 指针名;   //释放单个
        delete []指针名;   //释放多个
(3)常类型---使用const修饰说明的类型;他的值是不能被更新的,定义时必须进行初始化;
      http://blog.csdn.net/Eric_Jo/article/details/4138548
      C++允许在程序编译期间就使用const常量,如 const int i = 10; -->char chT[i];//使用i,在C中只有宏定义才可以
      const 可以放在类型说明符前或后都行
    **const 修饰指针时有些特殊
        char * const pName = XX;//其中被修饰的指针是常指针不可变,但其指向的变量(*pName)是可变的
        const char * pName = XX;//其中被修饰的指针是指向字符串常量的,pName是可变的,而指针可变
    **在类中 const 成员只能通过成员初始化列表形式初始化
(3-1)const    
    1、用const 修饰函数的参数
        对于非内部数据类型的输入参数,应该将“值传递”的方式改为“const 引用传递”,目的是提高效率。例如将void Func(A a) 改为void Func(const A &a)。
        对于内部数据类型的输入参数,不要将“值传递”的方式改为“const 引用传递”。否则既达不到提高效率的目的,又降低了函数的可理解性。例如void Func(int x) 不应该改为void Func(const int &x)。
    2、用const 修饰函数的返回值
        如果给以“指针传递”方式的函数返回值加const 修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const 修饰的同类型指针。
        const char * GetString(void);
        如下语句将出现编译错误:
        char *str = GetString();
        正确的用法是
        const char *str = GetString();
        如果函数返回值采用“值传递方式”,由于函数会把返回值复制到外部临时的存储单元中,加const 修饰没有任何价值。
    3、const 成员函数(const的作用:说明其不会修改数据成员)
        任何不会修改数据成员的函数都应该声明为const 类型。如果在编写const 成员函数时,不慎修改了数据成员,或者调用了其它非const 成员函数,编译器将指出错误,这无疑会提高程序的健壮性。
        a. const对象只能访问const成员函数,而非const对象可以访问任意的成员函数,包括const成员函数.
        b. const对象的成员是不可修改的,然而const对象通过指针维护的对象却是可以修改的.
        c. const成员函数不可以修改对象的数据,不管对象是否具有const性质.它在编译时,以是否修改成员数据为依据,进行检查.
        e. 然而加上mutable修饰符的数据成员,对于任何情况下通过任何手段都可修改,自然此时的const成员函数是可以修改它的。
        
(4)存储类型
    extern存储类型:引用其他文件中定义的变量
    static存储类型:静态全局变量不能被其他文件引用(只在本文件有效),即不能被extern引入其他文件
            (1)函数体内修饰的静态变量,在调用函数期间其值维持不变
            (2)在模块内定义的静态全部变量,不能被其他模块引用,此静态变量被限制在本模块内有效
            (3)在不同.c文件中要声明名称相同全局变量,需用static限定(原因如(2))
            (4)在类中的static变量属于整个类,不限于某个类对象
            (5)类中的static函数,不能被this指针引用(this指针区分实例,static不属于某个实例);因而只能访问static变量。
    regsiter存储类型:仅用于int、char变量
(5)引用与指针的区别
    (1)引用定义时必须被初始化,指针可不被初始化
    (2)引用初始化后不可变,指针可变
    (3)引用不可指向空,指针可以指向NULL
(6)全局变量,全局static变量;局部变量,static局部变量;函数,static函数区别
    (1)全局变量与全局static变量在存储形式上没什么区别;全局变量的作用域是整个源文件,而全局static则被限制在本模块文件中有效,在同一源的其他文件中不可用;(改变了他的作用域)
    (2)局部变量存储于栈,局部static变量存储于静态存储区(多次调用其值存在)(改变了存储方式)
    (3)statit函数在内存中只有一份,普通函数则在每个调用中都有一份;static只在当前源文件有效
(7)内存分配
    (1)栈:int a;
    (2)堆:int *a = new int(10);
    (3)全局区(静态区)static:全局变量与静态变量放于一块;初始化的全局变量与静态变量放于一块,未初始化的全局变量与静态变量放于相邻区域;调用完后有系统释放
    (4)文字常量区:常量字符串放于此,结束后由系统释放。 char *pch = "1234"; //pch在栈,"1234"文字常量区
    (5)代码区:存放函数体二进制代码
(8).h中声明类,.cpp中定义的意义?
    (1)提高了编译效率。编译一次生产.obj后再次引用时不必重新编译,提高了编译效率。
(9)类内定义的成员函数属性
    (1)类内定义的成员函数会自动变成内联函数,在函数调用地方编译阶段会进行代码替换。
(10)成员函数通过什么区分不同对象成员数据?
    (1)this指针;他指向对象的首地址,因而能区别。
(11)C++编译器自动为类生产的四个成员函数?
    (1)构造:调用顺序是先调用基类的,在进行成员初始化(成员初始化列表),最后调用自己的
    (2)析构:
    (3)拷贝构造:类初始化给类对象,类对象为函数形参,返回类对象时调用;当涉及到动态存储分配时需重写
    (4)赋值函数:
(12)什么情况下使用类成员初始化列表
    (1)类成员是const时
    (2)类成员是对象,而该对象没有无参构造函数时
    (3)类成员是引用时(引用必须被初始化)
(13)类与对象的区别:类是抽象,对象时实例
(14)类成员访问属性:
    (1)public:可以被1.该类中的函数、2.子类的函数、3.其友元函数访问,也可以由4.该类的对象访问。
    (2)private:私有类型,只能由1.该类中的函数、2.其友元函数访问。不能被任何其他访问,该类的对象也不能访问。
    (3)protected:保护性,可以被1.该类中的函数、2.子类的函数、以及3.其友元函数访问。但不能被类的对象访问。
    注:友元函数包括3种:设为友元的普通的非成员函数;设为友元的其他类的成员函数;设为友元类中的所有成员函数。
    http://www.cnblogs.com/york-hust/archive/2012/06/01/2530799.html
(15)虚函数与普通函数区别
    (1)virtual,虚函数有虚函数表与虚函数指针,虚函数指针就是虚函数接口,普通函数没有;内联和构造函数不能为virtual函数
    
(16)进程与线程
    (1)线程:CreateThread/AfxBeginThread开启
    (2)进程:CreateProcess开启
(17)SendMessage与PostMessage
    (1)SendMessage:阻塞的,消息处理完后才能继续执行
    (2)PostMessage:非阻塞的,

(18)CMemoryState:查看内存使用情况,解决内存泄露问题的
    (1)CMemoryState oldMem, newMem, diffMem; -->oldMem.Checkpoint()--->oldMem.DumpAllObjectsSince();newMem.Checkpoint()--->difMem.Difference(oldMem, newMem); -->difMem.DumpStatistics();
(19)系统会自动打开或关闭的标准文件
    (1)标准输入----stdin
    (2)标准输出----stdout
    (3)标准出错输出----stderr
(20)指针集中典型应用
    (1)int *p[n];
    (2)int (*)p[n]
    (3)int *p();
    (4)int (*)p();
(21)struct/union的区别
    (1)结构和联合都是由多个不同的数据类型成员组成,但在任何时刻,联合中值存在被选中的一个成员;(union所有成员公用一块地址,而结构各成员存于不同地址)
    (2)联合不同成员赋值,将会重写其他成员,但机构不会。
(22)struct/class区别
    (1)struct成员默认是共有的,class默认是private的。
(23)bool、float、指针与"零"比较
    (1)bool:(bool == false)
    (2)float:(fabs(float) == 0)
    (3)指针:(指针 == NULL)、(*指针 == 0)
(24)想在main()后执行一段代码
    (1)可以用_onexit注册一个函数,他会在main()后运行;
        --使用格式:_onexit(int fun()) ,其中函数fun()必须是带有int类型返回值的无参数函数;
        --_onexit() 包含在头文件cstdlib中,cstdlib为c语言中的库函数;
        --无论函数_onexit() 放到main中任意位置,它都是最后执行。
        #include <stlib.h>
        int Fun1(void){..};
        main()
        {
            _onexit(Fun1);
        }
(25)memcpy、strcpy、sprintf区别
    (1)strcpy:操作对象是字符串(以"\0"结束的)
    (2)sprintf:目的是字符串,但是源的形式不限
    (3)memcpy:内存拷贝;必须指出拷贝长度;不限类型
(26)字符串、数字互转
    (1)字符串转数字
        strTint()
        {
            char *pStr = "123456";
            int n = 0;
            int nTemp = 0;
            while (*pStr != '\0')
            {
                nTemp = *pStr - '0';
                n = n * 10 + nTemp;
                pStr++;
            }
        }
    (2)数字转字符串
        intTostr()
        {
            int n = 123456;
        }
(27)函数指针
    (1)获取函数指针:使用函数名(没有参数与括号)即可;
    (2)声明函数指针:如 double *pam(int a, int b);--->函数指针为double * (*pf)(int a, int b); 赋值:pf = pam;
    (3)使用函数指针:pf(1,2);或(*pf)(1, 2);都可以
    (4)使用数组:double *(*pa[3])(param...) = {Fun1, Fun2, Fun3..};--->pa[i](param...);
    (5)使用自动类型自动推断:auto pb = pa;-->pb(param...); 或 auto pb = &pa;-->(*pb)(param);
    (6)使用typedef:typedef double *(*pf)(param..);-->pf Test[n];-->Test[i](param...);...
(28)函数重载、模板
    (1)
(29)显示实例化(explicit instantiation)和显示具体化(explicit specialization)的区别:
    (1)形式上:
        显示实例化:  template  void  Swap<int> (int ,int);
        显示具体化:  template <> void Swap<int> (int,int);
                    或template <>  void Swap   (int,int);
        从中我们可以看出区别在于前者以 template 打头,后者以template<> 打头
    (2)含义上:
        显示实例化:使用 Swap() 模板生成 int 类型的函数定义,即使用函数模板,用具体的 int 来代替函数模板中的泛型类型,这样就不用额外写函数定义。
        显示具体化:不使用Swap()模板生成函数定义,而使用专门的、独立的(即显示具体化所定义的函数)函数定义来显示的为 int 类型生成函数定义,显示具体化要有额外的函数定义部分。
    (3)隐式实例化(implicit instantiation)比较简单,它是在函数调用时根据参数的具体类型来确定函数模板中的泛型类型。
    (4)显示实例化,隐式实例化和显示具体化统称为具体化(specialization),它们的相同之处在于都是用具体的类型的函数定义,而不是通用描述

(30)成员函数和友元函数如何区分
    (1)友元函数和类的成员函数都可以访问类的私有成员变量或者是成员函数,但是他们调用的形式不同。
    (2)成员函数是属于类的,所以调用的时候是通过指针this调用的。而友元函数不属于类,当然也不能有this指针了,也就是在友元函数中不能出现this指针。同时友元函数是有关键字friend修饰。
    (3)相同点:
            对类的存取方式相同,可以直接存取类的任何存取控制属性的成员
            可以通过对象存取形参、函数体中该类类型对象的所有成员
       不同点:  
            成员函数有this指针,友元函数没有
            友元函数不能被继承,就像父亲的朋友不一定是儿子的朋友
    (4)成员函数是类定义的一部分、必须通过特定对象来调用;成员函数可以隐式访问调用类成员,无需成员运算符;友元不是类组成部分,因此被称为直接函数调用,他不能隐式访问类对象成员,必须将成员运算符作为参数传递。
    (5)=/()/[]/->必须由成员函数来进行运算符重载
(30-1)友元函数、类的非静态成员函数、静态成员函数的区别
      类中申明的函数相对于类来说有三层意思:
            1.有this指针
            2.函数在类的作用区域中
            3.可以访问类中私有部分
            4.可以被继承
    (1)非静态成员函数具有1234、静态成员函数具有234、友元函数具有3;
    (2)静态成员函数的地址可用普通函数指针储存,而普通成员函数地址需要用 类成员函数指针来储存。
    (3)静态成员函数不可以调用类的非静态成员。因为静态成员函数不含this指针。
    (4)静态成员函数不可以同时声明为 virtual、const、volatile函数.
    (5)静态成员是可以独立访问的,也就是说,无须创建任何对象实例就可以访问。
(31)类中特殊的成员变量(常变量、引用、静态)的初始化方法
    (1)常量和引用,必须通过成员初始化列表进行初始化。
    (2)静态成员变量的初始化也颇有点特别,是在类外初始化且不能再带有static关键字,其本质见文末。
    (3)只有静态常量成员变量,才可以在声明时就初始化;//也可在类外初始化,同(2);const static int i;--const ClassName::i = 10;
(32)什么不能被继承
    (1)构造函数、析构函数、赋值运算符、友元
(32)什么情况下需要重写赋值运算符
    (1)派生类构造函数使用了new、new[]运算符来初始化指针成员时使用;
(33)公有继承(public)、私有继承(private)、保护继承(protected)是常用的三种继承方式。
    (1)公有继承(public)
        公有继承的特点是基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态,而基类的私有成员仍然是私有的,不能被这个派生类的子类所访问。
        (1) 基类成员对其对象的可见性:
            公有成员可见,其他不可见。这里保护成员同于私有成员。
        (2) 基类成员对派生类的可见性:
            公有成员和保护成员可见,而私有成员不可见。这里保护成员同于公有成员。
        (3) 基类成员对派生类对象的可见性:
            公有成员可见,其他成员不可见。
        所以,在公有继承时,派生类的对象可以访问基类中的公有成员;派生类的成员函数可以访问基类中的公有成员和保护成员。这里,一定要区分清楚派生类的对象和派生类中的成员函数对基类的访问是不同的。
    (2)私有继承(private)
        私有继承的特点是基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。
        (1) 基类成员对其对象的可见性:    
            公有成员可见,其他成员不可见。
        (2) 基类成员对派生类的可见性:
            公有成员和保护成员是可见的,而私有成员是不可见的。
        (3) 基类成员对派生类对象的可见性:
            所有成员都是不可见的。
        所以,在私有继承时,基类的成员只能由直接派生类访问,而无法再往下继承。
    (3)保护继承(protected)
        保护继承的特点是基类的所有公有成员和保护成员都成为派生类的保护成员,并且只能被它的派生类成员函数或友元访问,基类的私有成员仍然是私有的。

(34)继承问题---赋值兼容规则(对象切片)
    (1)派生类对象可以赋值给基类对象,这是把派生类对象中从基类继承来的隐藏对象赋值给基类对象。反过来不行,因对对于基类来说,没有派生类扩充的内容。
    (2)派生类对象地址可以赋值给基类对象指针,这是把派生类对象中从基类继承来的隐藏对象赋值给基类对象。反过来不行,因对对于基类来说,没有派生类扩充的内容。
    (3)派生类对象可以初始化给基类对象的引用,这是把派生类对象中从基类继承来的隐藏对象赋值给基类对象。反过来不行,因对对于基类来说,没有派生类扩充的内容。
(35)继承中的虚函数表---_vfptr
    (1)单继承
        1、继承但没有重写虚函数:虚函数表中会依次显示基类的->虚函数+(若派生类有自身的虚函数则加在后面面,但基类虚函数指针访问范围只是基类虚函数),如:|Base::f1()|Base::f2()|....|Psl::pf()....|
        2、继承并重写了虚函数:虚函数表中基类的虚函数地址会被派生类的地址覆盖->虚函数+(若派生类有自身的虚函数则加在后面面,但基类虚函数指针访问范围只是基类虚函数),如:|Psl::f1()|Base::f2()|....|Psl::pf()....|//其中f1()就是重写的虚函数
    (2)多继承
        1、继承但没有重写虚函数:按继承顺序第一个基类虚函数表中会依次显示基类的->虚函数+(若派生类有自身的虚函数则加在后面面,但基类虚函数指针访问范围只是基类虚函数),如:|Base::f1()|Base::f2()|....|Psl::pf()....|
                                 其余基类的虚函数表中只显示自身的虚函数,不会加派生类自身的虚函数
        2、继承并重写了虚函数:所有基类的虚函数表中的虚函数地址会被派生类所重写的同名、同参函数的地址覆盖。
                                第一个基类中虚函数表:虚函数+(若派生类有自身的虚函数则加在后面面,但基类虚函数指针访问范围只是基类虚函数),如:|Psl::f1()|Base::f2()|....|Psl::pf()....|//其中f1()就是重写的虚函数,psl表示派生类
                                其余基类的虚函数表为:虚函数;如:|Psl::f1()|Base::f2()|....|//其中f1()就是重写的虚函数,psl表示派生类
(36)define只是文本替换,注意有必要的括号:如#define MULTI(a,b) (a)*(b)//注意要是没有括号那么要是MULTI((10+10),(20+10))这样调用时会出错
(37)字符串拷贝时注意空间:注意字符串末尾还有一个'\0'字符
(38)多态
    一般来说,多态分为两种,静态多态和动态多态。静态多态也称编译时多态,主要包括模板和重载。而动态多态则是通过类的继承和虚函数来实现,
    当基类和子类拥有同名同参同返回的方法,且该方法声明为虚方法,当基类对象,指针,引用指向的是派生类的对象的时候,基类对象,指针,引用在调用基类的方法,实际上调用的是派生类方法。这就是动态多态。
(39)泛型指针、原生指针和智能指针
    (1)
    (2)
    (3)
(40)结构体对齐详解
    1、许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的起始地址的值是某个数k的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的对齐模数(alignment modulus)。这种强制的要求一来简化了处理器与内存
    之间传输系统的设计,二来可以提升读取数据的速度。
    2、结构体对齐包括两个方面的含义:
        (1)结构体总长度
        (2)结构体内各数据成员的内存对齐,即该数据成员相对结构体的起始位置;
    3、结构体大小的计算方法和步骤:
        1)将结构体内所有数据成员的长度值相加,记为sum_a;
        2)将各数据成员为了内存对齐,按各自对齐模数而填充的字节数累加到和sum_a上,记为sum_b。对齐模数是#pragma pack指定的数值以及该数据成员自身长度中数值较小者。该数据相对起始位置应该是对齐模式的整数倍;
        3)将和sum_b向结构体模数对齐,该模数是【#pragma pack指定的数值】、【未指定#pragma pack时,系统默认的对齐模数(32位系统为4字节,64位为8字节)】和【结构体内部最大的基本数据类型成员】长度中数值较小者。结构体的长度应该是该模数的整数倍。

(41)explicit的作用
    1.在C++中,explicit关键字用来修饰类的构造函数,被修饰的构造函数的类,不能发生相应的隐式类型转换,只能以显示的方式进行类型转换。
      explicit使用注意事项:
        1)explicit 关键字只能用于类内部的构造函数声明上。
        2)explicit 关键字作用于单个参数的构造函数。
(42)C++函数参数和返回值三种传递方式:值传递、指针传递和引用传递 (着重理解)
    1.参数传递:
        每次调用函数时,都会重新创建该函数所有的形参,此时所传递的实参将会初始化对应的形参。形参的初始化与变量的初
        始化一样。
    2.函数返回:
        函数的返回值用于初始化在调用函数处创建的临时对象。用函数返回值初始化临时对象与用实参初始化形参的方法是一样
        的。
        返回非引用:在调用函数的地方会将函数返回值复制给临时对象。
        返回引用:当函数返回引用类型时,没有复制返回值。相反,返回的是对象本身。
    3.类型
        1.简单型值   非浮点型值的其他原生C++类型,以及任何类型的指针、引用。
        2.浮点型值   浮点型值值传递略有不同,具体的讲解,我们放到第四章。
        3.复杂型值   这里指的复杂型值,包括数组和自定义的类型(结构体和类)。
    4.在参数传递的过程中,有一个动作是必然会发生的,这就是从实参到形参的拷贝。
        1.在值传递过程中,拷贝的是变量的值(如有必要,调用拷贝构造函数)。
        2.在指针传递过程中,拷贝的则是指针的值,也就是所指向变量的地址。
        3.在引用过程中,拷贝的是引用所在内存中的值,其实也就是上文所说的常指针的值,总之拷贝的是个地址。
    ----而在函数内部,对拷贝进来的这个值的任何改变都不影响外部数据。而对指针所指变量或引用所表示的变量,
        则可能会有修改。
    5.返回值----函数的返回值是由eax传递出来的(浮点数则用浮点数寄存器ST0及浮点指令fld等)。    

   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值