Boolan_c++第4周笔记

革命尚未成功,同志仍需努力💪

1、导读

1) 泛型编程(Generic Programming)和面向对象编程(Object-Oriented Programming)是c++的技术主线。

推荐书记:《c++ primer》第五版;《c++ programming language》《effective c++》(有中文版)《effective modern c++》《the c++ standard library》《STL源码剖析》

模版库是用模版编程的思维做出来的。

2、Conversion Function(转换函数)

class A创建的对象转换成别的类型,或者将别的类型转为class A类型

class Fraction

{

public:

    Fraction(int num, int den = 1)

        :m_numerator(num), m_denominator(den) {   }

    operator double() const {      

//operator double() 想将这个类转换成double类型,double里面不可有参数,没有返回类型,转换不应有改变,通常加const

        return (double)(m_numerator / m_denominator);

}

private:

    int m_numerator;

    int m_denominator;

};

Fraction f(3,5);

double d = 4+f;   //调用operator double()将f转为0.6

3、non-explicit-one-argument ctor 不是explicit类型 一个参数有默认值,只需要给一个参数赋值即可(可以把别的东西转换成这种)

1)

class Fraction

{

public:

    Fraction(int num, int den = 1)

        : m_numerator(num), m_denominator(den) { }

    Fraction operator+(const Fraction& f)

        return Fraction(......);

private:

    int m_numerator;

    inr m_denominator;

}

Fraction f(3,5);

Fraction d2 = f+4;  //调用non-explicit ctor 将4转为Fraction(4,1),然后调用operator+

Fraction f(3,5); Fraction d2=f+4;//会报错,要根据使用判断函数,使用f+4上述代码中黄绿不可并存,

2)explicit-one-argument ctor

(explicit明白的,明确的)告诉编译器不要随便给我做事情,用到构造函数再调用,不可以把3变成3/1

class Fraction

{

    explict Fraction(int num, int den=1)

        :m_numerator(num), m_denominator(den) {  }

    operator double() const{

        return (double) (m_numerator / m_denominator);}

    Fraction operator+(const Fraction& f) {  //这里定义的加法,左右两边都应该是Fraction

        return Fraction(......);

}

private:

    int m_numerator;

    int m_denominator;

};

Fraction f(3,5);

Fraction d2=f+4;  //[Error] 4无法变成Fraction类型

explict大多数情况下都用在构造函数前面。

template<class Alloc>    // templete<typename name>

class vector<bool, Alloc>    //模版的偏特化,vector中存放的每一个值是bool类型

{

public:

    typedef  __bit_reference reference;

protected:

    reference operator[ ] (size_type n)   //对[ ]做重载,传回值是reference,应该传回bool值,但是现在传回的是reference,需要一个转换函数将其转换为bool值

        {return *(begin() + difference_type(n));}

...

}

struct  __bit_reference   

{

    unsigned int* p;

    unsigned int mask;

public:

    operator bool() const { return !(!(*p & mask));}  //转换函数,将reference值转换成bool值

...

4)pointer-like classes

<1>关于智能指针(比指针功能更多)

class对象像指针或者像函数

智能指针里面一定带有一个真正的指针,有* 和 -> 两种操作

左边大圈圈像指针,里面有个真正的指针px

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

}

<2> 关于迭代器

代表容器中一个元素,遍历容器

5、function-like classes,仿函数

如果class里面有 operator( )  则是仿函数

6、namespace  //不同团队开发代码,把自己团队的都放到一个namespace下,防止和别人重名

namespace jj01

{ }

namespace jj02

{ }

测试:

int main(int argc, char** argv)

{

    jj01::test_member_template();

    jj02::test_template_template_param();

}


c++模板

模板是实现代码重用机制的一种工具,可以实现类型参数化,把类型定义为参数,从而实现代码可重用

模板分类:函数模版和类模版,成员模版。函数模版针对参数类型不同的函数;类模版仅针对数据成员和成员函数类型不同的类

注意:模版的声明或定义只能在全局,命名空间或类范围内进行。不能在局部范围,函数内进行,如不可在main()函数中声明或定义一个模版。


7、class template,类模板

设计一个类其某些变量可以被用户任意改变

8、Function Template,函数模板

函数模板使用时不用写类型

//学过c的童鞋们一定都写过函数sum吧,当时是这样写的:

int sum(int a,int b){ return a+b;}//实现了整数的相加

//如果再想同时实现小数的相加,就再多写个小数的相加。普通实现我就不写了,知道函数重载的童鞋们会这样写:

int sum(int a, int b){

//第一个function 

 return a+b;}

double sum(double a,double b){

//第二个function 

 return a+b;}

//这样我们就可以只用一个sum函数 就可以实现整数相加与小数相加。

//但是这样我们还是要定义两个函数。

//C++考虑了怎么避免这种重复的操作,代码如下: 函数模板的声明。

templete <typename T>

T sum(T a, T b)

{return a+b;}

//只需要定义一个函数与只使用一个函数实现两数相加。

9、member template,成员模板

标黄部分定义了一个模版,该模版是在模版内部,称为成员模版;T1,T2允许变化,U1,U2也可以变化

语法:

template <class T1, class T2>

    template <class u1, class u2>

反之是不可以的

template<typename _Tp>

class shared_ptr:public __shared_ptr<_Tp>

{

...

    template<typename _Tp1>

    explicit shared_ptr(_Tp1* __p)

            :__shared_ptr<_Tp>(__p) { }

...

};

Base1* ptr = new Derived1;

shared_ptr<Base1>sptr(new Derived1);


10、模版特化(某些独特的类型要做特殊设计,将模版局部的特征化)

模版泛化,有一个类型,用时指定

template <class Key>

struct hash {  };  //泛化


template<>  //  以下为特化。Key被绑定,所以不在这里显示

struct hash<char>

{

//如果用户指定类型是char,int,long,可以用以下代码

    size_t operator () (char x) const {return x;}  //对()做重载

};

template<>

struct hash<int>

{

    size_t operator() (int x) const { return x; }

};

template<>

struct hash<long>

{

    size_t operator() (long x) const { return x; } 

};

使用  cout << hash<long> () (1000); 会去找有对应的特化,则用特化,1000的()是重载,1000是long x。


11、模版偏特化(局部特化)

1)个数的偏

模版中有多个模版参数,此例中有两个,要绑定其中一个(绑定要依次从左到右)。

T被绑定到bool上,Alloc不确定也要写下来

2)范围的偏

任意类型 变成指针指向的类型

templete <typename T>

class C

{ ... };   //先写一个任意类型的 

templete <typename U>

class C<U*>   //当用户是指针类型的要用这个(偏特化)

{ ... };

根据用户不同的调用形式是否有指针,来调用不同段的代码


12、模版模版参数

template<typename T, template <typename T> class Container> //模版模版参数

class XCls

{

private:

    Container<T> c;

public:

    ......

};


13、c++标准库

标准库提供给我们:数据结构,容器,算法

标准库给出的要直接用 不需要自己写

编译器  Dev c++ 支持c++11。project     、Project Option

14、三个主题(c++11)

1)数量不定的模版参数

void print()  //最后剩零个参数调用此函数

{

}

template<typename T, typename...Types>  //参数很多个,把参数分为一个和一个包(...)

void print(const T& firdtArg, const Type&...args)

{

    cout << firstArg << endl;

    print(args...);   //先打印7.5,然后再调用print将剩下的参数分为一个和一包,再进行递归。

}

调用:print(7.5, "hello", bitset<16>(377),42);

%%一个和一包(pack)里面所做的操作任意

求一包里面参数个数:sizeof...(args)     //要加...

2)auto(since c++11)

以前版本:

list<string> c;

...

list<string>::iterator ite;

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

c++11:

list<string> c;

...

auto ite = find(c.begin(), c.end(), target);  编译器通过等号右边自动推出左边auto是什么

//下面写法是错误的

list<string> c;

...

auto ite;  //这里❌  编译器无法推测auto类型

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

3)ranged-base for

for(decl : coll) //decl是变量,coll是容器,将容器中值赋给左边变量,再进行下面计算

{ statement }

for(int i: {2,3,5,7,9,13,17,19})  //在c++11中容器可以直接用大括号列出来

{cout << i << endl;}

elem等同于容器中元素,类型不想写了用auto。*3之后不影响原来的值(用传值非方式)

for(auto& elem: vec) {elem *= 3;} 传引用,改变原来值。//引用就是指针

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

推荐阅读更多精彩内容