C++备忘录

时间:2023-08-18 17:25:23

  参考资料:

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

  结果:

  C++备忘录

  ● 在类中重载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 ;
}

  结果:

  C++备忘录

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

  结果:

  C++备忘录

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

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