• C++备忘录


      参考资料:

      1. 《C++编程思想(第一卷)》

      

      知识点:

      ● register变量:它是一种局部变量类型。它告诉编译器尽快访问该变量。一般会把变量放在寄存器中,但不保证一定会。不能得到或计算寄存器变量的地址,且寄存器变量必须在模块中声明。无全局或静态寄存器变量。

      注意:要相信编译器,尽量避免使用register关键字。

      ● static变量:①方法内部的静态变量在该方法首次调用时被初始化,并在以后的方法调用时保存该静态变量的值(记忆的效果)。

             ②当一个静态方法或变量在所有方法外时,意味着该变量只能在该文件中能被访问。也就说它的作用域是该文件,即使加了extern关键字。

      ● static成员变量既可以在构造函数中初始化,也可以在类外初始化。

      ● extern关键字extern关键字告诉编译器该变量或方法存在,尽管在当前被编译文件中没有被看到。而该变量或方法实际上可能定义在其它文件中或当前文件的下文。再次强调,externstatic不能共存。

      ● volatile关键字volatile修饰符则告诉编译器“你永远不知道它什么时候改变”,并阻止编译器进行基于该变量的稳定性的优化。主要是多线程环境下。强迫读,强迫写,从而保证数据一致。

      ● 内部链接internal linkage和外部链接external linkage

        ● cast强制类型转换cast告诉编译器不要进行类型检查,并把该变量当做期望的类型。

      ● struct无成员的时候,长度为1Byte(每一个对象都必须拥有一个唯一地址)。有时候,不会将函数和其它包含在Struct的长度中,只计成员变量。C++中结构体可用访问控制符:public、protected和private。

    #ifndef STACK_H
    #define STACK_H
    
    ////code here
    
    #endif
    View Code

    ● 不要在头文件中使用directives(using xxxxx),因为这样会失去对该namespace命名空间的保护(在CPP文件中使用)。Don't put using directives in header files.

    friend关键字的意义就是打破访问控制符的作用,从而也打破了封装。嵌套类或结构体也需要通过friend关键字才能访问外部类的私有成员。结构体所有的访问控制符都会在程序运行之前消失(仅仅是内存区域),且发生在编译阶段。

    struct X;
    
    struct Y
    {
        void f(X*);
    };
    
    struct X
    {
    private:
        int i;
    public:
        void inialize();
        friend void g(X*, int); // 全局友元
        friend void Y::f(X*); // 成员友元
        friend struct Z; // 整个结构体都是友元
        friend void h();
    };
    
    void X::inialize()
    {
        i = 0;
    }
    
    void g(X* x, int i)
    {
        x->i = i;
    }
    
    void Y::f(X* x)
    {
        x->i = 47;
    }
    
    struct Z
    {
    private:
        int j;
    public:
        void intialize();
        void g(X* x);
    };
    
    void Z::intialize()
    {
        j = 99;
    }
    
    void Z::g(X* x)
    {
        x->i += j;
    }
    
    void h()
    {
        X x;
        x.i = 100;
    }
    View Code

      ● classstruct在C++中基本是等同的,除了class默认为private,而struct默认为public

      ● 最好自定义构造方法,而不是让编译器去做这件事。

      ● union可以由构造方法和析构方法。

    union U
    {
    private:
        int i;
        float f;
    public:
        U(int a);
        U(float b);
        ~U();
        int read_int();
        float read_float();
    };
    
    U::U(int a) { i = a; }
    U::U(float b) { f = b; }
    U::~U() { cout << "Destructor of U
    "; }
    int U::read_int() { return i; }
    float U::read_float() {return f; }
    
    class SuperVar
    {
        enum
        {
            character,
            integer,
            floating_point
        } vartype;
        union
        {
            char c;
            int i;
            float f;
        };
    public:
        SuperVar(char ch);
        SuperVar(int ii);
        SuperVar(float ff);
        void print();
    };
    
    SuperVar::SuperVar(char ch)
    {
        vartype = character;
        c = ch;
    }
    
    SuperVar::SuperVar(int ii)
    {
        vartype = integer;
        i = ii;
    }
    
    SuperVar::SuperVar(float ff)
    {
        vartype = floating_point;
        f = ff;
    }
    
    void SuperVar::print()
    {
        switch(vartype)
        {
            case character:
                cout << "character: " << c << endl;
                break;
            case integer:
                cout << "integer: " << i << endl;
                break;
            case floating_point:
                cout << "float: " << f << endl;
                break;
        }
    }
    View Code

      ● const关键字const修饰符就是告诉编译器“它永远不会被改变”。  

      ● 类中的const成员变量的意思是:在该对象的生命周期中,该常数一直存在。每一个对象可能包含不同的常数。类中的static const的意思是:该类的所有对象,都共享同一个常数(运行时常数)。

      ● 类中的const函数的意思是:它不会改变类中成员变量的值。

      ● 成员函数的const参数的意思是:该参数不会在该函数中被改变。

    const成员变量的周期是每一个类对象,它只能在类的构造函数中初始化(C++ 11后不是了)。要想定义类的常量,需要使用枚举enum { var = 20};该枚举不占用类对象的空间,且在编译时被全部求值。  

    class Widget
    {
        const int i;
        // const int i = 10; //C++ 11以后支持
        static int j;
    public:
        Widget(int s) : i(s) { j = 20; }
    };
    
    int Widget::j = 30;
    View Code

      ● mutable关键字将bitwise的const对象中的成员变得可以被修改(logic const)。

    class Z
    {
        int i;
        mutable int j;
    public:
        Z();
        void f() const;
    };
    
    Z::Z() : i(0), j(0){}
    
    void Z::f() const
    {
        j++;
    }
    
    int main()
    {
        const Z zz;
        zz.f();
        return 0;
    }
    View Code

      ● ROMability(往ROM里写)需要满足的条件:①首先该对象必须是bitwise的const对象;②classstruct必须没有用户自定义的构造方法和析构方法;③基类或成员对象必须没有用户自定义的构造方法和析构方法。

      ● 类中的inline函数直到该类声明结束时(大括号结束时)才会被评估。

    class Forward
    {
        int i;
    public:
        Forward() : i(1) {}
        int f() const { return g() + i; }
        int g() const { return i; }
    };
    View Code

      ● C++引用C的函数(“C”) || C引用C++的函数(“C++”)。 => _func1_int_char || _func1

    extern "C" float func1(int a, char b);
    
    extern "C"
    {
        float func1(int a, char b);
        double func2(int a, char b);
    }
    
    extern "C"
    {
        #include "Test.h"
    }
    View Code

      ● 引用reference(&)有点类似于常数指针,能被自动解引用dereferenced。使用引用的一些规则:①当引用被创建时,必须被初始化;②一旦引用被初始化给一个对象,它就不能被改变去引用另一个对象;③不能有NULL引用,引用必须与合法的内存关联。

      ● Unary一元运算符重载:成员方法和全局方法。

      成员方法

    class Byte
    {
        unsigned char b;
    public:
        Byte(unsigned char bb = 0) : b(bb) {}
    
        const Byte& operator + () const
        {
            return *this;
        }
    
        const Byte operator - () const
        {
            return Byte(-b);
        }
    
        const Byte operator ~ () const
        {
            return Byte(~b);
        }
    
        Byte operator ! () const
        {
            return Byte(!b);
        }
    
        Byte* operator& ()
        {
            return this;
        }
    
        const Byte& operator ++ ()
        {
            b++;
            return *this;
        }
    
        const Byte operator ++ (int)
        {
            Byte before(b);
            ++b;
            return before;
        }
    
        const Byte& operator -- ()
        {
            b--;
            return *this;
        }
    
        const Byte operator -- (int)
        {
            Byte before(b);
            --b;
            return before;
        }
    };
    View Code

      全局方法

    class Integer
    {
        long i;
        Integer* This() { return this; }
    public:
        Integer(long ll = 0) : i(ll) {}
    
        friend const Integer& operator + (const Integer& a);
        friend const Integer& operator - (const Integer& a);
        friend const Integer operator ~ (const Integer& a);
        friend Integer* operator & (Integer& a);
        friend int operator ! (const Integer& a);
    
        friend const Integer& operator ++ (Integer& a); // Prefix
        friend const Integer operator ++ (Integer& a, int); // Postfix
    
        friend const Integer& operator -- (Integer& a); // Prefix
        friend const Integer operator -- (Integer& a, int); // Postfix
    
        void print() { cout << i << endl; }
    };
    
    const Integer& operator + (const Integer& a)
    {
        return a;
    }
    
    const Integer& operator - (const Integer& a)
    {
        return Integer(-a.i);
    }
    
    const Integer operator ~ (const Integer& a)
    {
        return Integer(~a.i);
    }
    
    Integer* operator & (Integer& a)
    {
        return a.This();
    }
    
    int operator ! (const Integer& a)
    {
        return !a.i;
    }
    
    const Integer& operator ++ (Integer& a)
    {
        a.i++;
        return a;
    }
    
    const Integer operator ++ (Integer& a, int)
    {
        Integer before(a.i);
        ++a.i;
        return before;
    }
    
    const Integer& operator -- (Integer& a)
    {
        a.i--;
        return a;
    }
    
    const Integer operator -- (Integer& a, int)
    {
        Integer before(a.i);
        --a.i;
        return before;
    }
    View Code

       ● Binary二元运算符重载:成员方法和全局方法。

       注意:=只能是成员方法。

      成员方法

    class Byte
    {
        unsigned char b;
    public:
        Byte(unsigned char bb = 0) : b(bb) {}
    
        const Byte operator + (const Byte& right) const
        {
            return Byte(b + right.b);
        }
        const Byte operator - (const Byte& right) const
        {
            return Byte(b - right.b);
        }
        const Byte operator * (const Byte& right) const
        {
            return Byte(b * right.b);
        }
        const Byte operator / (const Byte& right) const
        {
            return Byte(b / right.b);
        }
        const Byte operator % (const Byte& right) const
        {
            return Byte(b % right.b);
        }
    
        const Byte operator ^ (const Byte& right) const
        {
            return Byte(b ^ right.b);
        }
        const Byte operator & (const Byte& right) const
        {
            return Byte(b & right.b);
        }
        const Byte operator | (const Byte& right) const
        {
            return Byte(b | right.b);
        }
    
        const Byte operator << (const Byte& right) const
        {
            return Byte(b << right.b);
        }
        const Byte operator >> (const Byte& right) const
        {
            return Byte(b >> right.b);
        }
    
        Byte& operator = (const Byte& right)
        {
            if (this == &right) return *this;
            b = right.b;
            return *this;
        }
    
        Byte& operator += (const Byte& right)
        {
            if (this == &right)
            {
                char temp = right.b;
                b += temp;
            }
            else
            {
                b += right.b;
            }
    
            return *this;
        }
        Byte& operator -= (const Byte& right)
        {
            if (this == &right)
            {
                char temp = right.b;
                b -= temp;
            }
            else
            {
                b -= right.b;
            }
    
            return *this;
        }
        Byte& operator *= (const Byte& right)
        {
            if (this == &right)
            {
                char temp = right.b;
                b *= temp;
            }
            else
            {
                b *= right.b;
            }
    
            return *this;
        }
        Byte& operator /= (const Byte& right)
        {
            if (this == &right)
            {
                char temp = right.b;
                b /= temp;
            }
            else
            {
                b /= right.b;
            }
    
            return *this;
        }
        Byte& operator %= (const Byte& right)
        {
            if (this == &right)
            {
                char temp = right.b;
                b %= temp;
            }
            else
            {
                b %= right.b;
            }
    
            return *this;
        }
    
        Byte& operator ^= (const Byte& right)
        {
            if (this == &right)
            {
                char temp = right.b;
                b ^= temp;
            }
            else
            {
                b ^= right.b;
            }
    
            return *this;
        }
        Byte& operator &= (const Byte& right)
        {
            if (this == &right)
            {
                char temp = right.b;
                b &= temp;
            }
            else
            {
                b &= right.b;
            }
    
            return *this;
        }
        Byte& operator |= (const Byte& right)
        {
            if (this == &right)
            {
                char temp = right.b;
                b |= temp;
            }
            else
            {
                b |= right.b;
            }
    
            return *this;
        }
    
        Byte& operator >>= (const Byte& right)
        {
            if (this == &right)
            {
                char temp = right.b;
                b >>= temp;
            }
            else
            {
                b >>= right.b;
            }
    
            return *this;
        }
        Byte& operator <<= (const Byte& right)
        {
            if (this == &right)
            {
                char temp = right.b;
                b <<= temp;
            }
            else
            {
                b <<= right.b;
            }
    
            return *this;
        }
    
        int operator == (const Byte& right) const
        {
            return b == right.b;
        }
        int operator != (const Byte& right) const
        {
            return b != right.b;
        }
        int operator < (const Byte& right) const
        {
            return b < right.b;
        }
        int operator > (const Byte& right) const
        {
            return b > right.b;
        }
        int operator <= (const Byte& right) const
        {
            return b <= right.b;
        }
        int operator >= (const Byte& right) const
        {
            return b >= right.b;
        }
        int operator && (const Byte& right) const
        {
            return b && right.b;
        }
        int operator || (const Byte& right) const
        {
            return b || right.b;
        }
    
        void print() const { cout << hex << int(b) << endl; }
    };
    View Code

      全局方法

    class Integer
    {
        long i;
        Integer* This() { return this; }
    public:
        Integer(long ll = 0) : i(ll) {}
    
        friend const Integer operator + (const Integer& left, const Integer& right);
        friend const Integer operator - (const Integer& left, const Integer& right);
        friend const Integer operator * (const Integer& left, const Integer& right);
        friend const Integer operator / (const Integer& left, const Integer& right);
        friend const Integer operator % (const Integer& left, const Integer& right);
    
        friend const Integer operator ^ (const Integer& left, const Integer& right);
        friend const Integer operator & (const Integer& left, const Integer& right);
        friend const Integer operator | (const Integer& left, const Integer& right);
    
        friend const Integer operator << (const Integer& left, const Integer& right);
        friend const Integer operator >> (const Integer& left, const Integer& right);
    
        friend Integer& operator += (Integer& left, const Integer& right);
        friend Integer& operator -= (Integer& left, const Integer& right);
        friend Integer& operator *= (Integer& left, const Integer& right);
        friend Integer& operator /= (Integer& left, const Integer& right);
        friend Integer& operator %= (Integer& left, const Integer& right);
    
        friend Integer& operator ^= (Integer& left, const Integer& right);
        friend Integer& operator &= (Integer& left, const Integer& right);
        friend Integer& operator |= (Integer& left, const Integer& right);
    
        friend Integer& operator <<= (Integer& left, const Integer& right);
        friend Integer& operator >>= (Integer& left, const Integer& right);
    
        friend int operator == (const Integer& left, const Integer& right);
        friend int operator != (const Integer& left, const Integer& right);
        friend int operator < (const Integer& left, const Integer& right);
        friend int operator > (const Integer& left, const Integer& right);
        friend int operator <= (const Integer& left, const Integer& right);
        friend int operator >= (const Integer& left, const Integer& right);
        friend int operator && (const Integer& left, const Integer& right);
        friend int operator || (const Integer& left, const Integer& right);
    
    
        void print() const { cout << i << endl; }
    };
    
    const Integer operator + (const Integer& left, const Integer& right)
    {
        return Integer(left.i + right.i);
    }
    const Integer operator - (const Integer& left, const Integer& right)
    {
        return Integer(left.i - right.i);
    }
    const Integer operator * (const Integer& left, const Integer& right)
    {
        return Integer(left.i * right.i);
    }
    const Integer operator / (const Integer& left, const Integer& right)
    {
        return Integer(left.i / right.i);
    }
    const Integer operator % (const Integer& left, const Integer& right)
    {
        return Integer(left.i % right.i);
    }
    
    const Integer operator ^ (const Integer& left, const Integer& right)
    {
        return Integer(left.i ^ right.i);
    }
    const Integer operator & (const Integer& left, const Integer& right)
    {
        return Integer(left.i & right.i);
    }
    const Integer operator | (const Integer& left, const Integer& right)
    {
        return Integer(left.i | right.i);
    }
    
    const Integer operator << (const Integer& left, const Integer& right)
    {
        return Integer(left.i << right.i);
    }
    const Integer operator >> (const Integer& left, const Integer& right)
    {
        return Integer(left.i >> right.i);
    }
    
    Integer& operator += (Integer& left, const Integer& right)
    {
        if (&left == &right)
        {
            long temp = right.i;
            left.i += temp;
        }
        else
        {
            left.i += right.i;
        }
    
        return left;
    }
    Integer& operator -= (Integer& left, const Integer& right)
    {
        if (&left == &right)
        {
            long temp = right.i;
            left.i -= temp;
        }
        else
        {
            left.i -= right.i;
        }
    
        return left;
    }
    Integer& operator *= (Integer& left, const Integer& right)
    {
        if (&left == &right)
        {
            long temp = right.i;
            left.i *= temp;
        }
        else
        {
            left.i *= right.i;
        }
    
        return left;
    }
    Integer& operator /= (Integer& left, const Integer& right)
    {
        if (&left == &right)
        {
            long temp = right.i;
            left.i /= temp;
        }
        else
        {
            left.i /= right.i;
        }
    
        return left;
    }
    Integer& operator %= (Integer& left, const Integer& right)
    {
        if (&left == &right)
        {
            long temp = right.i;
            left.i %= temp;
        }
        else
        {
            left.i %= right.i;
        }
    
        return left;
    }
    
    Integer& operator ^= (Integer& left, const Integer& right)
    {
        if (&left == &right)
        {
            long temp = right.i;
            left.i ^= temp;
        }
        else
        {
            left.i ^= right.i;
        }
    
        return left;
    }
    Integer& operator &= (Integer& left, const Integer& right)
    {
        if (&left == &right)
        {
            long temp = right.i;
            left.i &= temp;
        }
        else
        {
            left.i &= right.i;
        }
    
        return left;
    }
    Integer& operator |= (Integer& left, const Integer& right)
    {
        if (&left == &right)
        {
            long temp = right.i;
            left.i |= temp;
        }
        else
        {
            left.i |= right.i;
        }
    
        return left;
    }
    
    Integer& operator >>= (Integer& left, const Integer& right)
    {
        if (&left == &right)
        {
            long temp = right.i;
            left.i >>= temp;
        }
        else
        {
            left.i >>= right.i;
        }
    
        return left;
    }
    Integer& operator <<= (Integer& left, const Integer& right)
    {
        if (&left == &right)
        {
            long temp = right.i;
            left.i <<= temp;
        }
        else
        {
            left.i <<= right.i;
        }
    
        return left;
    }
    
    int operator == (const Integer& left, const Integer& right)
    {
        return left.i == right.i;
    }
    int operator != (const Integer& left, const Integer& right)
    {
        return left.i != right.i;
    }
    int operator < (const Integer& left, const Integer& right)
    {
        return left.i < right.i;
    }
    int operator > (const Integer& left, const Integer& right)
    {
        return left.i > right.i;
    }
    int operator <= (const Integer& left, const Integer& right)
    {
        return left.i <= right.i;
    }
    int operator >= (const Integer& left, const Integer& right)
    {
        return left.i >= right.i;
    }
    int operator && (const Integer& left, const Integer& right)
    {
        return left.i && right.i;
    }
    int operator || (const Integer& left, const Integer& right)
    {
        return left.i || right.i;
    }
    View Code

      ● 重载逗号运算符

    #include <iostream>
    
    using namespace std;
    
    class After
    {
    public:
        const After& operator, (const After&) const
        {
            cout << "After::operator, ()" << endl;
            return *this;
        }
    };
    
    class Before {};
    
    Before& operator, (int, Before& b)
    {
        cout << "Before::operator, ()" << endl;
        return b;
    }
    
    int main()
    {
        After a,b;
        a, b;
        Before c;
        2, c;
        return 0;
    }
    View Code

      ● 重载->运算符

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    class Obj
    {
        static int i, j;
    public:
        void f() { cout << i++ << endl; }
        void g() { cout << j++ << endl; }
    };
    
    int Obj::i = 47;
    int Obj::j = 11;
    
    class ObjContainer
    {
        vector<Obj*> a;
    public:
        void add(Obj* obj) { a.push_back(obj); }
    
        class SmartPointer;
        friend SmartPointer;
        class SmartPointer
        {
            ObjContainer& oc;
            unsigned int index;
         public:
            SmartPointer(ObjContainer& objc) : oc(objc), index(0) {}
    
            bool operator++()
            {
                if (index >= oc.a.size()) return false;
                if (oc.a[++index] == 0) return false;
                return true;
            }
    
            bool operator++(int)
            {
                return operator++();
            }
    
            Obj* operator->() const
            {
                return oc.a[index];
            }
        };
    
        SmartPointer begin()
        {
            return SmartPointer(*this);
        }
    };
    
    int main()
    {
        const int sz = 10;
        Obj o[sz];
        ObjContainer oc;
        for (int i = 0; i < sz; i++)
            oc.add(&o[i]);
    
        ObjContainer::SmartPointer sp = oc.begin();
    
        do
        {
            sp->f();
            sp->g();
        } while(++sp);
    
        return 0;
    }
    View Code

      ● 重载[ ]运算符

    class IntArray
    {
        enum { sz = 5};
        int localArray[sz];
    public:
        IntArray() { memset(localArray, 0, sz * sizeof(*localArray)); }
        int& operator[] (int index)
        {
            return localArray[index];
        }
    };
    View Code

    ● 重载->*运算符(pointer-to-member dereference operator),用以模拟built-in pointer-to-member。

    #include <iostream>
    
    using namespace std;
    
    class Dog
    {
    public:
        int run(int i) const
        {
            cout << "run...
    ";
            return i;
        }
    
        int eat(int i) const
        {
            cout << "eat...
    ";
            return i;
        }
    
        int sleep(int i) const
        {
            cout << "ZZZ...
    ";
            return i;
        }
    
        typedef int (Dog::*PMF)(int) const;
    
        class FunctionObject
        {
            Dog* ptr;
            PMF pmem;
        public:
            FunctionObject(Dog* wp, PMF pmf) : ptr(wp), pmem(pmf)
            {
                cout << "FunctionObject constructor
    ";
            }
    
            int operator()(int i) const
            {
                cout << "FunctionObject::operator()
    ";
                return (ptr->*pmem)(i);
            }
        };
    
        FunctionObject operator->*(PMF pmf)
        {
            cout << "operator->*" << endl;
            return FunctionObject(this, pmf);
        }
    };
    
    int main()
    {
        Dog w;
        Dog::PMF pmf = &Dog::run;
        cout << (w->*pmf)(1) << endl;
    
        pmf = &Dog::sleep;
        cout << (w->*pmf)(2) << endl;
    
        pmf = &Dog::eat;
        cout << (w->*pmf)(3) << endl;
        return 0;
    }
    View Code

      ● 不可重载的运算符有:作用域操作符:: ,条件运算符? : , 点(成员)操作符.以及.*, 预处理符#

      ● explicit关键字与自动类型转化

    #include <iostream>
    
    using namespace std;
    
    class One
    {
    public:
        One() {}
    };
    
    class Two
    {
    public:
        //Two(const One&) {}
        explicit Two(const One&) {}
    };
    
    class Three
    {
        int i;
    public:
        Three(int ii = 0, int = 0) : i(ii){}
    };
    
    class Four
    {
        int x;
    public:
        Four(int xx) : x(xx){}
        operator Three() const { return Three(x); }
    };
    
    int main()
    {
        One one;
        //Two two = one;
        Four four(1);
        Three three = four;
    
        return 0;
    }
    View Code

      ● 重载全局 new & delete

    #include <cstdlib>
    #include <cstdio>
    
    using namespace std;
    
    void* operator new(size_t sz)
    {
        void* m = malloc(sz);
        if (!m) puts("out of memory");
    
        return m;
    }
    
    void operator delete(void* m)
    {
        puts("operator delete");
        free(m);
    }
    
    class S
    {
        int i[100];
    public:
        S() { puts("S::S()"); }
        ~S() { puts("S::~S()"); }
    };
    
    int main()
    {
        puts("creating & deleting an int");
        int* p = new int[47];
        delete p;
    
        puts("
    creating & deleting an s");
        S* s = new S();
        delete s;
    
        puts("
    creating & deleting S[3]");
        S* sa = new S[3];
        delete []sa;
        return 0;
    }
    View Code

      结果:

      

      ● 在类中重载new & delete

    #include <iostream>
    #include <cstddef>
    #include <fstream>
    #include <new>
    
    using namespace std;
    
    ofstream out("Framis.out");
    
    class Framis
    {
        enum { sz = 10 };
        char c[sz];
        static unsigned char pool[];
        static bool alloc_map[];
    public:
        enum { psize = 100 };
        Framis() { out << "Framis()
    "; }
        ~Framis() { out << "~Framis()... "; }
        void* operator new(size_t) throw(bad_alloc);
        void operator delete(void*);
    };
    
    unsigned char Framis::pool[psize * sizeof(Framis)];
    bool Framis::alloc_map[psize] = { false };
    
    void* Framis::operator new(size_t) throw(bad_alloc)
    {
        for (int i = 0; i < psize; i++)
        {
            if (!alloc_map[i])
            {
                out << "using block " << i << " ... ";
                alloc_map[i] = true;
                return pool + (i * sizeof(Framis));
            }
        }
    
        out << "out of memory" << endl;
        throw bad_alloc();
    }
    
    void Framis::operator delete(void* m)
    {
        if(!m) return;
    
        unsigned long block = (unsigned long)m - (unsigned long)pool;
        block /= sizeof(Framis);
        out << "freeing block " << block << endl;
        alloc_map[block] = false;
    }
    
    int main()
    {
        Framis* f[Framis::psize];
        try
        {
            for (int i = 0; i < Framis::psize; i++)
                f[i] = new Framis;
    
            new Framis;
        }
        catch (bad_alloc)
        {
            cerr << "Out of memory!" << endl;
        }
    
        delete f[10];
        f[10] = 0;
        Framis* x = new Framis();
        delete x;
        for (int j = 0; j < Framis::psize; j++)
        {
            delete f[j];
        }
        return 0;
    }
    View Code

      ● 为数组重载new & delete1,

    #include <new>
    #include <fstream>
    
    using namespace std;
    ofstream trace("ArrayOperatorNew.out");
    
    class Widget
    {
        enum { sz = 10};
        int i[sz];
    public:
        Widget() { trace << "*"; }
        ~Widget() { trace << "~"; }
        void* operator new(size_t sz)
        {
            trace << "Widget::new: " << sz << " bytes" << endl;
            return ::new char[sz];
        }
    
        void operator delete(void* p)
        {
            trace << "Widget::delete" << endl;
            ::delete []p;
        }
    
        void* operator new[](size_t sz)
        {
            trace << "Widget::new[]: " << sz << " bytes" << endl;
            return ::new char[sz];
        }
        void operator delete[](void* p)
        {
            trace << "Widget::delete[]" << endl;
            ::delete []p;
        }
    };
    
    int main()
    {
        trace << "new Widget" << endl;
        Widget* w = new Widget;
        trace << "
    delete Widget" << endl;
        delete w;
        trace << "
    delete Widget[25]" << endl;
        Widget* wa = new Widget[25];
        trace << "
    delete []Widget" << endl;
        delete []wa;
        return 0;
    }
    View Code

      结果:

      

      ● new一个的对象的过程:先分内存,再调用构造函数。如果分配内存失败,抛出bad_alloc异常,且构造函数不会被调用。更多请参考:C++ new失败处理

      ● 构造函数初始化列表(constructor initializer list)对应着继承行为,都有冒号这种类似的结构。std::initializer_list<T>(C++11)类型的对象是一个轻量级的代理对象,里面的成员都是常量。 如:auto a = { 1, 2, 3 }。

      ● 构造函数和析构函数调用顺序:构造函数从父类开始,到最末端子类结束;析构函数调用过程与之相反。在初始化列表中的成员变量总是在父类构造函数被调用之后被调用,且按照在类中定义的顺序初始化;析构时,成员变量总是在析构函数执行后,按照在类中定义的顺序逆向释放空间。

      测试代码:

    #include <iostream>
    
    using namespace std;
    
    #define CLASS(ID) class ID {
    public:
        ID(int) { cout << #ID " constructor
    "; }
        ~ID() { cout << #ID  " destructor
    "; }
    };
    
    CLASS(BaseClass);
    CLASS(MemberOne);
    CLASS(MemberTwo);
    CLASS(MemberThree);
    CLASS(MemberFour);
    
    class SubClass : public BaseClass
    {
        MemberOne m1;
        MemberTwo m2;
    public:
        SubClass(int) : m2(2), m1(1), BaseClass(0)
        {
            cout << "SubClass constructor
    ";
        }
    
        ~SubClass()
        {
            cout << "SubClass destructor
    ";
        }
    };
    
    class SubSubClass : public SubClass
    {
        MemberThree m3;
        MemberFour m4;
    public:
        SubSubClass() : m3(3), SubClass(-1), m4(4)
        {
            cout << "SubSubClass constructor
    ";
        }
    
        ~SubSubClass()
        {
            cout << "SubSubClass destructor
    ";
        }
    };
    
    
    int main()
    {
        SubSubClass ssc;
        return 0;
    }
    View Code

      结果:

      

      ● 在C/C++中,#的功能是将其后边的宏参数进行字符串化操作,而##则被称为连接符,用来将两个子串Token连接为一个Token。

    #include <cstdio>
    
    #define lookup(x, format) printf(#x " = %" #format "
    ", x)
    #define lookupAgain(i) lookup(x##i, d)
    
    using namespace std;
    
    int main()
    {
        int i = 1;
        char* s = "hello world";
        float x = 2.0;
    
        lookup(i, d); // equal to printf("i = %d
    ", i)
        lookup(x, f); // equal to printf("x = %f
    ", x)
        lookup(s, s); // equal to printf("s = %s
    ", s)
    
        printf("
    ");
    
        int x1 = 1, x2 = 2, x3 = 3;
        lookupAgain(1); // equal to lookup(x1, d)
        lookupAgain(2); // equal to lookup(x2, d)
        lookupAgain(3); // equal to lookup(x3, d)
    
        return 0;
    }
    View Code

      结果:

      

      ● 私有继承与私有组件的区别在于,私有继承可以部分公共化父类的接口。

    #include <iostream>
    
    using namespace std;
    
    class Animal
    {
    public:
        void eat() const { cout << "I am eating..." << endl; }
        void speak() const { cout << "I am speaking..." << endl; }
        void sleep() const { cout << "I am sleeping..." << endl; }
        void sleep(int time) { cout << "I will sleep " << time << " minutes..." << endl;}
    };
    
    class Lion : Animal
    {
    public:
        using Animal::eat;
        using Animal::sleep; // Both sleep
    };
    
    int main()
    {
        Lion lion;
        lion.eat();
        lion.sleep();
        lion.sleep(20);
        return 0;
    }
    View Code

      ● 连接方法调用到方法体即绑定(binding)。绑定=前期绑定+后期绑定(动态绑定或运行时绑定)。C++ 通过vpointer指向的VTABLE实现的,关键字是virtual。具体参见C++对象模型的研究

      ● 在构造函数中调用虚函数,会调用当前类中的函数(就近原则),但可以通过Base::Method()的方式调用基类的函数。

      构造函数不能使用virtual修饰,单析构函数必须使用virtual修饰。纯析构函数必须由方法体(类外定义)。

      纯虚函数的使用:

    #include <cassert>
    
    using namespace std;
    
    class Pet
    {
    public:
        virtual void speak() const = 0;
        virtual void eat() const = 0;
        virtual void sleep() const = 0;
    
        virtual string getName () const { return "I am a pet"; };
    };
    
    void Pet::speak() const
    {
        cout << "Pet::speak()" << endl;
    }
    
    void Pet::eat() const
    {
        cout << "Pet::eat()" << endl;
    }
    
    class Dog : public Pet
    {
    public:
        void speak() const { Pet::speak(); }
        void eat() const { cout << "Dog::eat()" << endl; }
        void sleep() const { cout << "Dog::sleep()" << endl; }
    };
    
    int main()
    {
        Dog dog;
        dog.speak();
        dog.eat();
        dog.sleep();
        cout << dog.getName() << endl;
    
        return 0;
    }
    View Code
  • 相关阅读:
    轻量级数据持久层Seaking.PL简介--Query对象
    轻量级数据持久层Seaking.PL简介及建议征集
    Google秘密搜索入口
    异常,究竟抛向何处?
    [转]深入讲解ASP+ 验证
    .Net卸载程序的制作
    性能测试:Reflection VS CodeDom
    小心文件夹名称中的特殊字符
    [转]用Web标准进行开发
    使用ASP.Net Forms模式实现WebService身份验证
  • 原文地址:https://www.cnblogs.com/AmitX-moten/p/5592597.html
Copyright © 2020-2023  润新知