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\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

 

posted @ 2016-06-17 00:12  motein  阅读(503)  评论(0编辑  收藏  举报