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

3.2迭代器

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

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

使用示例

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

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

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

}

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

5.模板

5.1 类模板

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

使用方法

complex<double> c1(2.5,1.5);
complex<int> c2(2,6);

5.2 函数模板

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

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

5.3成员模板

template <class T1, class T2>
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 <class U1, class U2>
  pair(const pair<U1, U2>& p) : first(p.first), second(p.second) {}
};

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

5.4 specialization 模板特化

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

模板泛化

template <class Key>
struct hash { };

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

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

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

5.5.模板偏特化

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

个数上的偏

template<typename T, typaname Alloc=.......>
class vector
{
...
}
template<typename Alloc=......>
class vector<bool,Alloc>

可以绑定不定个数的模板

范围的偏

template <typename T>
class C
{
...
};
template<typename T>
class C<T*>
{
...
}

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

5.6 模板模板参数

template<typename T, 
                 template <typename T>
                       class Container>
               >

第二个参数为模板参数

5.7 c++11的三个主题

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

允许写任意个数的模板

template<typename T,typename... Types>
void print(const T& firstArg,const Types&...  args)
{
    cout<<firstArg<<endl;
    print(args...);
}

接受两组参数,第一组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<string> c;
...
list<string>::iterator ite;
ite = find(c.begin(),c.end(),target);

可改为

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

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

list<string> 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<<i<<endl;
}
vector<double> vec;
...
for( auto elem : vec){
    cout<<elem<<endl;
}//pass by value

for( auto& elem : vec){
    elem *= 3;
}
//pass by reference,对vector本身进行操作,而不是副本

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即算重载

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容