C++程序设计一些深层次的细节

本文预览:

  • 转换函数 与 non-explict-one-argument Ctor
  • pointer-like class
  • function-like class
  • Reference经验谈

前言

本篇会提到一些琐碎的东西,虽然有一些在我们编写代码的过程中不经常用到,但是都是一些帮助你理解C++底层次的东西。网上有人开玩笑说,一个java程序员学了三年,师傅对他说,你已经精通java了,可以下山了;一个C++程序员,学了十年,师傅对他说,你可以下山了,但是不要说你精通C++。这当然只是个笑话,但是从侧面反映出一个深刻的道理,那就是C++坑大水深,入坑需谨慎~。既然你已经入坑了,不想就此自费武功,那就好好修炼内功吧。

转换函数 与 non-explict-one-argument Ctor

转换函数是什么鬼?类型转换嘛,顾名思义。转换函数记住一句话就好了,有转出去和转进来之分。
举个例子:设计一个分数类 x/y

class Fraction {//这个分数类还是非常简单的嘛
public:
    Fraction(int x, int y = 1):_x(x),_y(y){}
    inline int x() const {return _x;}
    inline int y() const {return _y;}
    operator double() const
    {
        return (double)(_x ) / (double)(_y);
    }
    Fraction operator+(const Fraction& f)
    {
        return Fraction(...);
    }
private:
    int _x; //分子
    int _y; //分母
};

分数类设计好了,使用的时候出现问题了:

Fraction f(3,5);
double d = 4 + f;

一个整数加一个分数,能编译通过吗?我们是不是还需要重载一个+操作符来来实现运算呢?现在好像是不用了,编译器能通过编译,计算结果也是正确的。你也许已经注意到了:

    operator double() const
    {
        return (double)(_x ) / (double)(_y);
    }

这就是转换函数的语法,没有返回值类型,函数名称就已经说明了你需要转换出去的类型。C++编译器会这么在遇到 4+f的时候首先会去寻找operator+(int),都没有int可以稳定转成double, operator+(double)肯定是有的,double+double类型能通过吗?找找看Fraction能转成double类型吗?operator double(),定义了转换到double类型的函数,可以转换。

现在我们把转换函数去掉,Fraction不能转成double了:

Fraction f(3,5);
double d = f + 4;

我们也没有operator+(const double) ,但是编译能过吗?我们重载了一个operator+(const Fraction&),这个必须是要有的,没有重载+肯定是编译不过的,也就是说,我们这次的+,肯定是用到了operator+(const Fraction),那么好了,如果能编译通过,肯定是int转成了Fraction类型了。但是,我们不可能去修改C++语言内核,在int里也加一个转换函数吧。为题出在哪里了?它怎么自动转的,这就用到了non-explict-one-argument Ctor, 自动调用了Fraction的构造函数,把int转换成了Fraction。

注意:

Fraction(int x, int y = 1):_x(x),_y(y){}
// explict Fraction(int x, int y = 1):_x(x),_y(y){}

这种构造函数叫做non-explict-one-argument Ctor,前面没有explict修饰,并且只有一个实参,第二个参数是有默认值的,如果没有默认值就不能叫one-argument。如果没有加explict编译器是可以自行调用,把其他类型转进来的。加了explict,编译就不通过了。

pointer-like class

pointer-like class:把class设计出来当做指针用。在智能指针和迭代器都是这么设计的。

  1. 智能指针的设计
智能指针的设计

智能指针被C++设计用来管内存,写法相当固定,必须要重载的和->,解引用这个应该都是没有什么困惑,但是问题在->这个问题就出来了,sp->method()调用返回的是T啊,在第一次已经使用了->,返回的T*还怎么调用method(),C++语法定义了->有继续作用的特性。这个问题就解决了。我们第一次虽然使用了->,但是由于C++语法规定,->能继续作用,因此,智能指针这么设计是没有问题的。

  1. 迭代器的设计

迭代器在STL里大部分都被设计成了class,迭代器的使用方法也很像是指针,我们以list的迭代器来看,是如何重载指针的解引用和调用操作符的。

迭代器的设计

在list中*操作符将获取元素对象,也就是list_no
![Uploading 屏幕快照 2017-03-08 16.00.50_078916.png . . .]
de<T>的data部分;->操作符获得data的指针。这样,我们就能使用迭代器,直接获取list元素对象和调用相应的方法了。

function-like class 所谓仿函数

function-like class: 将类设计出来,当做函数使用,又叫仿函数。其实质就是在里面重载了()操作符

仿函数在STL中

STL里面的算法less实现:

template <class T>
struct less
{
     bool operator()(const T& x, const T& y) const {return x < y; }
}

这是算法吗?分明就是一个class,这是一个class吗?这不是仿函数吗?自己好像很少用到仿函数吧,C++11里面出现了lamda表达式之后对仿函数简直就是秒杀有没有。但是它确实在STL里面有大量的应用。

    bool ret = less<int>()(2,1);        //第一个()表示是一个临时对象,第二个()才真正调用了operator()
    cout<<ret<<endl;
    
    float d = plus<float>()(1.2,2.1);
    cout<<d<<endl;

以上是使用示例。

Reference经验谈

如果从内存角度看一个变量,那么变量大概可以分为三类:

  • value : 分配一块内存空间放值
  • pointer : 分配一块内存空间放地址
  • reference : 分配一块地址空间,放一个对象,这个对象代表了他所引用的对象
int x = 0;
int& r = x;
cout<<x<<endl;
cout<<&x<<endl;
cout<<sizeof(x)<<endl;

cout<<r<<endl;
cout<<&r<<endl;
cout<<sizeof(r)<<endl;

你所看到的r和x所有的都是一样的,于是我们称reference是object的别名。但是它的内部实现是指针,但是它屏蔽了指针的概念和用法,在用法上和它所引用的对象是一样的。

关于引用需要知道:

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

推荐阅读更多精彩内容