C++備忘錄

  參考資料:html

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

  

  知識點:編程

  ● register變量:它是一種局部變量類型。它告訴編譯器儘快訪問該變量。通常會把變量放在寄存器中,但不保證必定會。不能獲得或計算寄存器變量的地址,且寄存器變量必須在模塊中聲明。無全局或靜態寄存器變量。數組

  注意:要相信編譯器,儘可能避免使用register關鍵字。多線程

  ● static變量:①方法內部的靜態變量在該方法首次調用時被初始化,並在之後的方法調用時保存該靜態變量的值(記憶的效果)。ide

         ②當一個靜態方法或變量在全部方法外時,意味着該變量只能在該文件中能被訪問。也就說它的做用域是該文件,即便加了extern關鍵字。函數

  ● static成員變量既能夠在構造函數中初始化,也能夠在類外初始化。測試

  ● extern關鍵字extern關鍵字告訴編譯器該變量或方法存在,儘管在當前被編譯文件中沒有被看到。而該變量或方法實際上可能定義在其它文件中或當前文件的下文。再次強調,externstatic不能共存。優化

  ● volatile關鍵字volatile修飾符則告訴編譯器「你永遠不知道它何時改變」,並阻止編譯器進行基於該變量的穩定性的優化。主要是多線程環境下。強迫讀,強迫寫,從而保證數據一致。ui

  ● 內部連接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\n"; }
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...\n";
        return i;
    }

    int eat(int i) const
    {
        cout << "eat...\n";
        return i;
    }

    int sleep(int i) const
    {
        cout << "ZZZ...\n";
        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\n";
        }

        int operator()(int i) const
        {
            cout << "FunctionObject::operator()\n";
            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("\ncreating & deleting an s");
    S* s = new S();
    delete s;

    puts("\ncreating & 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()\n"; }
    ~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 << "\ndelete Widget" << endl;
    delete w;
    trace << "\ndelete Widget[25]" << endl;
    Widget* wa = new Widget[25];
    trace << "\ndelete []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\n"; }\
    ~ID() { cout << #ID  " destructor\n"; }\
};

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\n";
    }

    ~SubClass()
    {
        cout << "SubClass destructor\n";
    }
};

class SubSubClass : public SubClass
{
    MemberThree m3;
    MemberFour m4;
public:
    SubSubClass() : m3(3), SubClass(-1), m4(4)
    {
        cout << "SubSubClass constructor\n";
    }

    ~SubSubClass()
    {
        cout << "SubSubClass destructor\n";
    }
};


int main()
{
    SubSubClass ssc;
    return 0;
}
View Code

  結果:

  

  ● 在C/C++中,#的功能是將其後邊的宏參數進行字符串化操做,而##則被稱爲鏈接符,用來將兩個子串Token鏈接爲一個Token。

#include <cstdio>

#define lookup(x, format) printf(#x " = %" #format "\n", 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\n", i)
    lookup(x, f); // equal to printf("x = %f\n", x)
    lookup(s, s); // equal to printf("s = %s\n", s)

    printf("\n");

    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
相關文章
相關標籤/搜索