第2节
防卫式声明,防止重复include引起的问题(guard)
1 2 3 4 5
| //complex.h #ifndef _COMPLEX_ #def _COMPLEX_ ... #endif
|
第3节
inline 内联函数
构造函数
1 2 3 4 5 6 7 8 9
| public: complex(double r = 0,double i = 0) :re(r),im(i) //上面的默认值是推荐用法 {} ... complex c1(2,1) complex c2 complex* c3 = new complex(4)
|
第4节
数据是private
参数、返回值尽可能拿引用传递:除了返回值需要新创建对象的情况
能加const的函数尽量加const
1
| type function () const { return result}
|
第6节
操作符重载
1 2 3
| complex::operator += (const complex& r){ return }
|
1 2 3 4 5
| //ostream不加const ostream& operator << (ostream& os, const complex& x) { return os << '(' << real(x) << ',' << imag(x) << ')'; }
|
第7节
1 2 3 4 5 6 7 8 9 10 11 12
| class String { public: String(const char* cstr = 0); String(const String& str); String& operator =(const String& str); ~String() char* get_c_str() const {return mdata};
private: char* m_data; }
|
拷贝构造(浅拷贝会内存溢出)
1 2 3 4 5
| inline String::String(const String& str) { m_data = new char[ strlen(str.m_data) + 1]; strcpy(m_data,str.m_data); }
|
拷贝赋值
1 2 3 4 5 6 7 8 9 10
| inline String::operator = (const string& str) { //不使用这个自我赋值判断,会刹掉自己 if(this == &str) retrun *this delete[] m_data; m_data = new char[ strlen(str.m_data) + 1]; strcpy(m_data,str.m_data) return *this; }
|
第8节
new :先分配内存,再调用ctor
delete:先调用析构函数,再释放内存
array new 要搭配 array delete使用
第15 16 17 18节
转换函数 ,构造方法也可以当转换函数转,比如4转为4/1
explicit :加在构造方法前面,表示必须得显示调用
1 2 3 4 5 6 7 8 9 10 11
| class Fraction { public: Fraction(int num,int den=1) : m_numberator(m), m_denominato {} operator double() const{ return (double)(a/b) } ... Fraction f(3,5) double d=4+5
|
1 2 3
| Fraction operator+(const Fraction& f){ return Fraction(...); }
|
pointer like classes 智能指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| template<class T> class shared_ptr { public: T& operator*() const { return *px; } T* operator->() const { return px; } shared_ptr(T* P) :px(p){} private: T* px; long* pn; }
|
Function-like classes
1 2 3 4 5
| template <class T> struct identity{ const T& operator()(const T& x) const {return x;} }
|
第19 - 25节
namespace 可以代码放一个文件进行,然后用namespace分割
类模板、函数模板、成员模板,函数模板使用时无需指定类型
1 2 3 4 5 6 7 8 9 10 11 12
| template <class T1,class T2> struct pair{ T1 first; T2 second; pair():first(T1()),second(T2); pair(const T1& a,const T2& b): first(a),second(b){} template <class U1,class U2> pair(const pair<U1,U2>& p): first(p.first),second(p.second){} }
|
模板特化,可以理解为限定类的模板特殊设计
1 2 3 4 5 6
| template <> struct hash<char>{ size_t operator()(char x) const{ return x; } }
|
模板模板参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| template<typename T, template <typename T>> class Container > class XCLs{ private: Container<T>c; public: ... }
template<typename T> using Lst = list<T, allocator<T>>;
//XCLs<string, list> mylst1; 错的 XCLs<string,Lst> mylst2;
|
模板偏特化
1 2 3 4 5 6 7 8 9
| template<class T,class Alloc=...> class vector<bool,Alloc>{ ... }
template <typename T> //指针 class C<T*>{ }
|
第27节
auto 关键字 必须得让编译器能推出你的变量是什么
1 2 3 4 5
| list<string> c; ... list<string>::iterator ite; ite = find(c.begin(),c.end,target); auto ite = find(c.begin(),c.end,target);
|
1 2 3 4 5
| for (auto eleme : vec){ }
for (auto& eleme : vec){ }
|
第28节
1 2 3 4 5 6 7
| int x = 0; int* p = &x; int& r = x; //r代表x 现在r, x 都是0 int x2 = 5; //等于把5赋值给x r = x2; //r 不能重新代表其它物体,现在r x都是5 int& r2 = r; //r2 x 都是5
|
1 2 3
| double image(const double& im){...} double image(const double im){...} //不能共存 Ambiguity
|
const属于签名的一部分,有const和没有const可以并存
第30-31节
vptr和vtbl
先通过指针 找到函数表再找到第n个 再调用
(*(p->vptr)[n])(p);
(* p->vptr[n] )(p);
编译器三个条件就会动态绑定
1.指针调用 2.向上转型 3.虚函数
(*(this -> vptr)[n])(this);
第33-38节
当成员函数的const和 non-const版本同时存在,const object只会调用const版本,non-const object只会调用non-const版本
new 和 delete可以重载
1 2 3 4
| inline void* operator new(size_t size) { return myAlloc(size);} inline void operator delete(void* ptr) { myfree(ptr);}
|
可以对成员的new /delete 做重载,写到类里
如果想使用globals
1 2 3
| Foo* pf = ::new Foo; ::delete pf //将使用全局的new 和delete
|
数组在内存中的size是countsize + unit * count
我们可以重载class member operator new(),写多个版本,每个声明必须有独特的参数列,且第一个必须是size_t,其余参数是new指定的placement arguments为初值。小括号内的便是placement arguments
1
| Foo* pf = new(300,'c') Foo;
|
可以重载class member operator delete(),写出多个版本,调不到,大师说老版本的能调到,在new异常的时候
operator new()在标准库的用处,多分配一些内存