美文网首页c++学习笔记
c++学习笔记之类

c++学习笔记之类

作者: chzphoenix | 来源:发表于2017-12-12 19:38 被阅读5次

    c++学习笔记系列:

    http://blog.csdn.net/column/details/17301.html

    1、预处理器封套:

    #ifndef XXX_H
    #define XXX_H
    ...
    class xxx{
    ...
    }
    ...
    #endif
    

    如果没有文件包含此头文件,XXX_H被定义并包含这个头文件;如果已经包含,则不再定义和包含。
    为了防止多次包含同一个头文件,尤其包含套包含的时候。注意命名要大写和下划线。

    2、对象的sizeof

    sizeof一个对象得到的是所有数据成员的大小。
    因为函数不存储在对象中,而是由编译器创建独立于所有对象的函数副本,所有对象共享函数副本。

    3、访问对象数据成员和成员函数

    对象名或对象引用的情况 a.b a.b()
    对象指针的情况 aPtr -> b aPtr -> b()

    4、工具函数

    工具函数即private函数

    5、析构函数

    ~类名() 在对象被撤销时被调用,某种意义上是与构造函数互补。

    class Time{
         Time(...){...}
         ~Time(){...}
    }
    

    注意:不接收任何参数,不返回任何参数,void也不行。
    一个类只能有一个析构函数,不允许重载。

    6、对象传参

    当对象作为参数或返回值时是传值参数,即传的是拷贝。
    所以当要使用真正对象需要传引用或指针。

    7、const对象\函数

    声明对象(注意位置):void name() const {....}
    对象声明const不能被修改,不能调用非const的成员函数。
    成员函数声明const不能修改对象,同样 不能调用非const的成员函数。
    (1)可以对const成员函数进行非const重载。编译器根据对象性质选择相应函数,const对象调用const函数;非 const对象调用非const函数
    (2)构造、析构函数不能声明const。

    8、成员初始化器

    int count;
    const in num;
    Time(int i, int j):count(i),num(j){...}
    

    所有数据成员都可以用成员初始化器来初始化,如上面的形式。
    但是const数据成员和引用的数据成员必须使用成员初始化器进行初始化,不能通过赋值初始化。
    (1)成员初始化器在构造函数体执行前执行。
    (2)建议将所有不修改对象的函数声明为const。

    9、组成

    即数据成员是一个其他类的对象。
    如果构造函数没有初始化某个成员,那么会隐式的调用该成员的默认构造函数。如果该成员的类没有默认构造函数,编译报错。

    10、friend函数和类(友元)

    class A{
         friend class B;
         friend void b(...);
    }
    

    友元可以访问原类中的非public成员和函数。
    (1)友元关系不传递,不对称。
    (2)友元函数不是成员函数
    (3)友元最好在数据成员及函数之前声明。
    (4)友元 模板类或 模板函数的情况,需要提前定义,否则报错,如:

    template<typename T> class B;
    class A{
         friend class<T> B;
    }
    

    (5)友元是非模板类的成员函数,也需要提前定义。

    10、this指针

    因为是指针,所以:this -> x 或 (*this) .x

    11、动态内存管理(new\delete)

    Time time; 或 int num[24]; 这样在定义时需要将所有内存分配(所有成员内存或所有元素内存),即使未使用到,且不能改变。
    使用动态内存管理实际上是在自由存储区分配内存区域,通过delete释放。

    Time *timePtr = new Time(....);
    delete timePtr;
    int *numsPtr = new int[24];
    delete [] numsPtr;
    

    (1)释放时先调用析构函数,再回收内存。数组释放时不加“[]”只调用第一个元素的析构函数。
    (2)不释放会造成内存泄漏
    (3)在编译时创建数组,大小必须用常量;而动态分配是可以使用任何表达式,如new int[a + b];
    (4)动态分配一个对象数组时,会使用对象的默认构造函数初始化
    (5)delete之后最好将指针设为0,如numsPtr=0。因为回收后内存空间中的信息还在,只是没有关系了,如果不注意访问了,会导致极端诡异无法复现的问题
    (6)尤其注意循环中要使用new,否则会出错,如下:

    for (int i = 0; i < 5; i++) {
         Node<int> node(i);
         Node<int> *ptr = &node;
    }
    

    运行时会发现每次循环ptr指针指向的地址是不变的,也就是说所有的循环一致用一个Node对象而不是每次新建,这样会导致逻辑错误。改成new动态分配后,每次循环都是新的对象。

    12、static

    static数据成员只能被初始化一次。
    int或枚举类型的const static数据成员可以在类定义中初始化;所有其他类型的数据成员必须在文件作用域(类定义外)定义并初始化。

    xxx.h
    class{
         ...
    private:
         static int a;
         ...
    }
    
    xxx.cpp
    ...
    int a = 1;
    ...
    

    (1)在.cpp文件中定义初始化static数据成员时不能声明static,应该在.h中声明为static。
    (2)如果成员是对象且有默认构造函数,可以不初始化。
    (3)public static数据成员在类外部使用:没有任何对象时Time::cout;有对象时time.count。
    (4)在static函数中不能使用this,否则编译错误。static函数不能被声明称const。

    13、代理类

    使用头文件虽然可以隐藏实现细节,但是依然暴露private数据成员或函数。
    使用代理类,只有一个private成员,即被代理类的对象指针。

    相关文章

      网友评论

        本文标题:c++学习笔记之类

        本文链接:https://www.haomeiwen.com/subject/idonixtx.html