【GeekBand】 C++面向对象高级编程(下) 首周

1.转换函数

class Fraction
{
public:
    explicit Fraction(int num, int den=1) 
      : m_numerator(num), m_denominator(den)
    { cout << m_numerator << ' ' << m_denominator << endl; }

     operator double() const {   
      return (double)m_numerator / m_denominator; 
     }

     Fraction operator+(const Fraction& f) {  
       cout << "operator+(): " << f.m_numerator << ' ' << f.m_denominator <<  endl;  
       //... plus
       return f; 
    } 

标黄的即为转换函数,函数名称为要转换的类型,无参数无返回值,且不改变成员数据,所以用const修饰函数
double d = 4 + f,编译器首先查找是否重载操作符+,若没有则看f是否有转换函数,若有则可以编译通过

2.non-explicit-one-argument ctor

蓝色段表示一个实参就够了,因为第二个实参有默认值
Fraction d2 = f+4; 调用non-explicit ctor 将4转为Fraction,然后调用operator+
如果non-explicit-one-argument ctor与转换函数并存时,Fraction d2=f+4;会出错,会造成编译器困惑,可以是Fraction与Fraction相加,也可以是Double与Double相加,因此要保证唯一性,不能有二义性。
在构造函数前加explicit,则无法将double转换为Fraction,一般只在构造函数前用

3 pointer-like classes

3.1 智能指针

template
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;
}
这种类要有指针的基本功能,首先可以用普通指针来初始化,其次要重载操作符* 和 ->
->有个特殊的地方,->用掉之后还会继续作用下去,所以sp->method(); 可以写成px->method();

3.2迭代器

主要用途是遍历容器,迭代器也是pointer-like classes,需要额外重载很多操作符,比如++、--等
reference operator*() const
{ return (*node).data;  }

pointer operator->() const
{ return &(operator*());  }
//->的重载中调用操作符*的重载
//即return的是&((*node).data)

使用示例

list::iterator ite;
...
*ite;// 获取一个Foo对象
ite->method();
//意思是调用Foo::method
//相当于(*ite).method
//相当于(&(*ite))->method

4.funtion-like classes,所谓仿函数

能够接受()的东西则称之为函数,或者像函数的类
template
struct identity :public unary_function {
    const T&;
    operator() (const T& x) const { return x; }

}

function-like classes 都重载了()操作符,都会继承奇特的base classes,unary_funtion 和 binary_function

5.模板

5.1 类模板

template
class complex
{
public:
    complex (T r = 0, T i = 0)
    : re(r),im(i) {  }
private:
    T re, im;
}

使用方法

complex c1(2.5,1.5);
complex c2(2,6);

5.2 函数模板

template 
inline
const T& min(const T& a, const T& b)
{
    return b < a? b : a;
}

编译器会对function template进行实参推导,编译器无需知道T的具体类型

5.3成员模板

template 
struct pair {
  typedef T1 first_type;
  typedef T2 second_type;

  T1 first;
  T2 second;
  pair() : first(T1()), second(T2()) {}
  pair(const T1& a, const T2& b) : first(a), second(b) {}

  template 
  pair(const pair& p) : first(p.first), second(p.second) {}
};

黄色段落即为成员模板,常见于标准库中类的构造函数,为的是让构造函数更有弹性

5.4 specialization 模板特化

面对某些独特的类型要做特殊的设计时需要用到模板特化

模板泛化

template 
struct hash { };

这种情况下,key可以是任意的class类型,因此称之为泛化
模板特化

template<>
struct hash{
    size_t operator() (char x) const {return x;}
};

如果<>中不是char,则调用泛化,若类型为特化中的已经指定的类型,则调用特化的内容

5.5.模板偏特化

偏特化就是如果这个模板有多个类型,那么只限定其中的一部分。包括个数上的偏以及范围上的偏

个数上的偏

template
class vector
{
...
}
template
class vector

可以绑定不定个数的模板

范围的偏

template 
class C
{
...
};
template
class C
{
...
}

上述即为范围的偏,从任意范围缩小为必须是指针,但指针可以指向任意类型

5.6 模板模板参数

template
                       class Container>
               >

第二个参数为模板参数

5.7 c++11的三个主题

5.7.1 variadic templates 数量不定的模板参数

允许写任意个数的模板

template
void print(const T& firstArg,const Types&...  args)
{
    cout<

接受两组参数,第一组firstArg,第二组为args数量不定,分为一个和一包(用...表示)

...就是一个所谓的pack(包)
用于template parameters,就是template parameters pack(模板参数包)

用于function parameter types,就是function parameter types pack(函数参数类型包)

用于function parameters,就是function parameters pack(函数参数包)

5.7.2 auto

list c;
...
list::iterator ite;
ite = find(c.begin(),c.end(),target);

可改为

list c;
...
auto ite = find(c.begin(),c.end(),target);

auto为编译器自动推导类型
错误用法

list c;
...
auto ite;
ite = find(c.begin(),c.end(),target);

该写法编译器无法推导ite的类型,声明对象时未赋值,无法推导其类型

5.7.3ranged-base for

for(dec1:col1){
    statement
}

编译器会找出容易col1中的每个元素,复制到dec1中,达到遍历容器的效果

for(int i : {2, 3, 4, 5, 6 })
{
    cout<
vector vec;
...
for( auto elem : vec){
    cout<

5.8 reference

三种变量 value pointer reference

int x = 0;
int* p = &r;
int& r = x; //r代表x,现在r,x都是0
int x2 = 5;

r = x2;  //r不能重新代表其他物体,现在r,x都是5
int r2 = r;// 现在r2是5(r2代表r,亦相当于代表x)

声明一个reference时,一定要有初始值,reference一旦声明后就不能再代表其他变量

reference的常见用途
a.用于参数传递,pass by reference
b.用于返回值,return by reference
通常不用于声明变量

double imag(const double& im) {}
double imag(const double im){}

函数签名相同,无法共存
const是函数签名的一部分,加了const即算重载

你可能感兴趣的:(【GeekBand】 C++面向对象高级编程(下) 首周)