参考资料:

  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

● 不要在头文件中使用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 = ;
} void g(X* x, int i)
{
x->i = i;
} void Y::f(X* x)
{
x->i = ;
} struct Z
{
private:
int j;
public:
void intialize();
void g(X* x);
}; void Z::intialize()
{
j = ;
} void Z::g(X* x)
{
x->i += j;
} void h()
{
X x;
x.i = ;
}

  ● 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;
}
}

  ● 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 = ; }
}; int Widget::j = ;

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

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

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

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

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

  ● 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"
}

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

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

  成员方法

class Byte
{
unsigned char b;
public:
Byte(unsigned char bb = ) : 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;
}
};

  全局方法

class Integer
{
long i;
Integer* This() { return this; }
public:
Integer(long ll = ) : 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;
}

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

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

  成员方法

class Byte
{
unsigned char b;
public:
Byte(unsigned char bb = ) : 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; }
};

  全局方法

class Integer
{
long i;
Integer* This() { return this; }
public:
Integer(long ll = ) : 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;
}

  ● 重载逗号运算符

#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;
, c;
return ;
}

  ● 重载->运算符

#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 = ;
int Obj::j = ; 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() {} bool operator++()
{
if (index >= oc.a.size()) return false;
if (oc.a[++index] == ) 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 = ;
Obj o[sz];
ObjContainer oc;
for (int i = ; i < sz; i++)
oc.add(&o[i]); ObjContainer::SmartPointer sp = oc.begin(); do
{
sp->f();
sp->g();
} while(++sp); return ;
}

  ● 重载[ ]运算符

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

● 重载->*运算符(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)() << endl; pmf = &Dog::sleep;
cout << (w->*pmf)() << endl; pmf = &Dog::eat;
cout << (w->*pmf)() << endl;
return ;
}

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

  ● 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 = , int = ) : 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();
Three three = four; return ;
}

  ● 重载全局 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[];
public:
S() { puts("S::S()"); }
~S() { puts("S::~S()"); }
}; int main()
{
puts("creating & deleting an int");
int* p = new int[];
delete p; puts("\ncreating & deleting an s");
S* s = new S();
delete s; puts("\ncreating & deleting S[3]");
S* sa = new S[];
delete []sa;
return ;
}

  结果:

  

  ● 在类中重载new & delete

#include <iostream>
#include <cstddef>
#include <fstream>
#include <new> using namespace std; ofstream out("Framis.out"); class Framis
{
enum { sz = };
char c[sz];
static unsigned char pool[];
static bool alloc_map[];
public:
enum { psize = };
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 = ; 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 = ; i < Framis::psize; i++)
f[i] = new Framis; new Framis;
}
catch (bad_alloc)
{
cerr << "Out of memory!" << endl;
} delete f[];
f[] = ;
Framis* x = new Framis();
delete x;
for (int j = ; j < Framis::psize; j++)
{
delete f[j];
}
return ;
}

  ● 为数组重载new & delete1,

#include <new>
#include <fstream> using namespace std;
ofstream trace("ArrayOperatorNew.out"); class Widget
{
enum { sz = };
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[];
trace << "\ndelete []Widget" << endl;
delete []wa;
return ;
}

  结果:

  

  ● 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(), m1(), BaseClass()
{
cout << "SubClass constructor\n";
} ~SubClass()
{
cout << "SubClass destructor\n";
}
}; class SubSubClass : public SubClass
{
MemberThree m3;
MemberFour m4;
public:
SubSubClass() : m3(), SubClass(-), m4()
{
cout << "SubSubClass constructor\n";
} ~SubSubClass()
{
cout << "SubSubClass destructor\n";
}
}; int main()
{
SubSubClass ssc;
return ;
}

  结果:

  

  ● 在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 = ;
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 = , x2 = , x3 = ;
lookupAgain(); // equal to lookup(x1, d)
lookupAgain(); // equal to lookup(x2, d)
lookupAgain(); // equal to lookup(x3, d) return ;
}

  结果:

  

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

#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();
return ;
}

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

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

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

  纯虚函数的使用:

#include <cassert>

using namespace std;

class Pet
{
public:
virtual void speak() const = ;
virtual void eat() const = ;
virtual void sleep() const = ; 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 ;
}

C++备忘录的更多相关文章

  1. MementoPattern(备忘录模式)

    /** * 备忘录模式 * @author TMAC-J * 用于存储bean的状态 */ public class MementoPattern { public class Memento{ pr ...

  2. C#设计模式-备忘录模式

    访问者模式的实现是把作用于某种数据结构上的操作封装到访问者中,使得操作和数据结构隔离.而本文要介绍的备忘者模式与命令模式有点相似,不同的是,命令模式保存的是发起人的具体命令(命令对应的是行为),而备忘 ...

  3. Vuex2.0+Vue2.0构建备忘录应用实践

    一.介绍Vuex Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化,适合于构建中大型单页应用. ...

  4. 设计模式03备忘录(java)

    先贴代码有空来写内容. 备忘录1 //简单的备忘录,只可以记录上一次修改前的状态,实现撤回一次的操作. class Student{ private String name; private Stri ...

  5. C#设计模式系列:备忘录模式(Memento)

    1.备忘录模式简介 1.1>.定义 备忘录模式在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可以将该对象恢复到原先保存的状态. 1.2>.使用频率 ...

  6. php实现设计模式之 备忘录模式

    <?php /*备忘录模式:在不破坏封装的前提下,获取对象的内部状态,并且在对象外保存该状态.这样就可以将该对象恢复到保存之前的状态(行为模式) * * 发起人:记录当前时刻的内部状态,负责定义 ...

  7. 十一个行为模式之备忘录模式(Memento Pattern)

    定义: 在不破坏原有封装的情况下,捕获一个对象的内部状态,并在对象之外保存.当对象出错或者无效是,可以根据该备忘录进行恢复. 结构图: Originator:原发类,被记录的对象,包含若干内部状态.一 ...

  8. 自适应备忘录 demo

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  9. java设计模式之备忘录模式

    备忘录模式 备忘录模式是一种软件设计模式:在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态.一听到备忘录这个字的时候想起了小小时打的游 ...

  10. 备忘录模式(Memento Pattern)

    在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态. 备忘录模式主要思想是——利用备忘录对象来对保存发起人的内部状态,当发起人需要恢复原 ...

随机推荐

  1. Leetcode: Encode String with Shortest Length && G面经

    Given a non-empty string, encode the string such that its encoded length is the shortest. The encodi ...

  2. [转]彻底征服 Spring AOP 之 实战篇

    Spring AOP 实战 看了上面这么多的理论知识, 不知道大家有没有觉得枯燥哈. 不过不要急, 俗话说理论是实践的基础, 对 Spring AOP 有了基本的理论认识后, 我们来看一下下面几个具体 ...

  3. gTest详解

    1. 安装使用 1.1 安装 在https://code.google.com/p/googletest/ 下载源码 进入msvc, 注意编译方式, 如果是dll, 选择 gtest-md 编译生成l ...

  4. leetcode:1-5题代码整理

    以下是这段时间抽时间刷的前5题,都是自己想的解法,或许不是最优解,只是整理下,方便日后优化提升 1. Two Sum: class Solution: # @return a tuple, (inde ...

  5. Ubuntu14.04安装OpenCV2.4.9

    1.安装依赖 sudo apt-get install build-essential libgtk2.0-dev libjpeg-dev libtiff4-dev libjasper-dev lib ...

  6. 响应式内容滑动插件jQuery.bxSlider

    bxSlider特性 1.充分响应各种设备,适应各种屏幕: 2.支持多种滑动模式,水平.垂直以及淡入淡出效果: 3.支持图片.视频以及任意html内容: 4.支持触摸滑动: 5.支持Firefox,C ...

  7. SVN在eclipse的整合应用

    目前很多的Java.Flex.Android开发人员是用eclipse作为开发工具的,本文主要介绍SVN在eclipse平台中的整合应用. 我的eclipse版本是Version: 3.4.2.本身没 ...

  8. Java反射遍历数组

    日志中有时候需要查看数组中的值,但是重载很多的打印函数,觉得很别扭.所以想通过反射,获取数组中的值,打印出来.Java提供了数组反射操作的类,之前没有关注过,提供的方法简单易用. public sta ...

  9. input失去隐藏光标(移动端)

    <input type="text" readonly name='lbinput' onfocus="lbinput.blur()">

  10. gulp操作基本功能.md

    gulp操作基本功能.示例代码: var gulp = require("gulp");//创建 gulp模块 var adel = require("del" ...