POPMART盲盒的本质不是赌博是什么?

POPMART盲盒的本质不是赌博是什么?

 

近日POPMART在香港上市,市值突破1000亿人民币,出生于1987年的创始人、董事长 王宁 夫妻合计持股超过56%,成为中国最成功的85后之一(王思聪出生于1988年1月,两者为同龄人)。

 

李国庆在抖音上表示,POPMART的成功在于抓住了95后的消费需求,然而,坦白说,无论是盲盒,还是抓娃娃,还是扭蛋,卖的都不是商品,而是带有赌博性质的消费体验。

 

众所周知,正常的消费,是商家明码标价,一个东西多少钱,顾客来购买。

 

然而POPMART盲盒、抓娃娃、扭蛋,都是商家不告诉你实际买到的到底是什么,你买到的可能是你喜欢的,可能是你不喜欢的,可能是很值钱的,可能是不值钱的,你买到的是什么全凭运气

 

这种商业模式并不是销售商品,而是销售带有赌博性质的消费体验,也就是赌博。

 

举例,你花59/69元去“买”一个POPMART盲盒,或者抓一次娃娃,或者扭一次扭蛋,“买到的”可能是你喜欢的玩具,也可能是你不喜欢的玩具,你支付的59/69元其实是赌资,“买到的”玩具就是你赌博的结果。

 

如果你想要买到你真正想买的那一个玩具,你要么买一整套,也就是捆绑销售,要么赌。

 

而如果你想要“买到”“隐藏款”玩具,你就要不断的下注,直到赌赢

 

这就是POPMART盲盒、抓娃娃、扭蛋的本质,也是所有赌博行为的本质。

 

下注 → 赌输/赌赢

 

59元赌一次

69元赌一次

708元赌一次

任君挑选

 

这和在小学门口摆摊“抽奖”有什么区别?

 

这不是赌博是什么?

 

盲盒自动贩卖机不是赌博机是什么?

 

事实上,一些特定款式的玩具已经和炒鞋一样成为了炒作的标的,存在非常大的人为炒作的空间,其实炒鞋也是同样的人为制造供应不足,炒高价格。

 

为了“买到”特定的玩具,买家只能大量重复购买不想要的玩具,这些非理性的消费将制造大量的塑胶垃圾,同时也存在捆绑销售的嫌疑。

 

POPMART盲盒、抓娃娃、扭蛋的主要消费群体是年轻人甚至未成年人,他们无法分辨什么是购买,什么是赌博,什么是理性消费,他们为了“买到”自己想要得到的玩具,很有可能会持续不断地下注,也就是持续不断地去赌,甚至沉迷其中

 

在此建议,如果POPMART真的是一家潮流玩具公司,就明码标价销售自己的玩具,销售自己的潮流,销售自己的文化,不要销售带有赌博性质的消费体验,不要引导年轻人甚至未成年人沉迷赌博。

 

有关部门应对带有赌博性质的销售行为进行明确的界定,不要让POPMART盲盒、抓娃娃、扭蛋继续消费那些意志力薄弱、没有分辨能力的年轻人甚至未成年人。

 

说得更赤裸裸一点,POPMART盲盒、抓娃娃、扭蛋其实是一种智力筛选,把没有分辨能力与意志力的群体筛选出来进行收割,或者说得更直白一点,就是把读书差的筛选出来进行收割,读书好的谁会傻到玩这个?

 

最后,希望POPMART等商家,卖什么就卖什么,卖多少钱就卖多少钱,不要卖赔率,不要把赌博包装成潮流文化。

 

通过吸引年轻人甚至未成年人赌博来赚钱、成为富豪,是可耻的。

 

转自:https://mp.weixin.qq.com/s/ycSYgdsVMtUYFVS1FrNfFA

全球最大自贸区正式生效,欧美打压中国的计划破产!

来源:天涯时事

 

2022年1月1日,全球最大自贸区《区域全面经济伙伴关系协定》,简称RCEP,正式生效。

可以说,这是元旦期间发生的一件大事,好事。

RCEP共涉及15个国家,中日韩澳新+东盟10国,是当前世界最大的自贸区。

全球最大自贸区正式生效,欧美打压中国的计划破产!

今天,我们重点和大家说说这件事诞生的背景和意义。

这件事诞生的背景主要有两个方面:

第一,WTO已经发展到极致,无法进一步促进经济的发展;

大家也知道,现在几乎所有国家都加入了WTO,WTO已经完成了它的历史使命。

WTO最重要的意义就是:它有效的降低了成员国之间的贸易关税。

降低关税有什么好处呢?

假设你以10块钱的价格购买一件外国商品,那么里面可能就包含2块钱的关税。降低或取消关税以后,商品的价格就会下降,你只需8块钱就能买到这件商品。

当商品价格出现下降的时候,购买的人就会增多,对商品的需求量就会增加;对商品需求增加,企业就会扩大生产,就需要建设更多的工厂、招收更多的人,就需要从其它国家进口更多的原材料。从而带动经济的发展。

但是,大家也知道:这种方式不可能无限制的带动经济发展的,它是有极限的。

目前,WTO的最大问题就是:它已经到达了它所能到达的极限,没有进一步发展的空间了。

这是什么意思呢?

我想了很久没有找到非常贴切的例子,举个不是很贴切的例子吧——虽然不严谨,但是能让你秒懂。

比如,我们村每年需要2000吨大米,但是由于村里的地比较少,一年只能产1500吨,差500吨。

由于粮食关系到全村人的性命,所以即使外面的粮食再便宜,我也不能都去买别人的,否则一旦哪天人家不卖我了,村人怎么办?所以,我必须要让村里人不能放弃自己的地——饿肚子总比饿死强吧。

为了让大家都吃饱肚子,差500吨粮食怎么办?

只能到别的村购买。

我们村周围有很多村,每个村的情况都是不同的:A村土地非常肥沃,生产一斤粮食只需要1块钱;B村土地比较肥沃,生产一斤粮食需要2块钱;C和D村土地一般,要3块钱;F村土地比较贫瘠,需要4块钱……

那么,我到底以什么价格来购买别村的粮食呢?

假如我以1.5元/斤的价格购买,那么只有A村会卖我粮食,因为其它村的粮食成本都大于1.5元。

但是,由于A村土地有限,他只能卖我100斤粮食,我还差400斤,怎么办?

所以,这个时候我就不能以1.5元/斤的价格去收购粮食,必须要提高价格。

如果我将价格提高到2.5元/斤,那么B村也会卖给我粮食了,假设B村也只能卖我100斤,那么我还差300斤。怎么办?

我只能继续提高价格。

当我把价格提高到3.5元/斤的时候,C和D村也会卖我粮食了,假设C村能卖我200斤,D村能卖我300斤……

大家算一下,当我把价格提到3.5元/斤的时候,A村能卖我100斤,B村能卖我100斤,C村能卖我200斤,D村能卖我300斤,合计就是700斤了,超过了我500斤的需求了。

没有办法,我为了让全村人都吃饱了就必须要把这700斤粮食都买来——因为在同样价格的前提下,我不能“歧视”任何一个村。

在WTO框架下,有一个最重要的原则:最惠国待遇

“最惠国待遇”是什么意思呢?

“最惠国待遇”就是指:如果一个成员国对另一个成员国的某产品降低关税,那么就必须同时对剩下的所有成员国都降低同等关税。

现在WTO存在的问题是什么?

就是关税没有办法进一步下降了:如果再下降,按照“最惠国待遇”原则,整个世界贸易体系就会乱套了。

假设,中国需要进口10亿吨粮食,现在我们对外国粮食加征的关税是20%,在这个关税的约束下,我们每年进口9亿吨粮食,差1亿吨。虽然差1亿吨,但是我们不能再降低关税了,因为如果再降,按照“最惠国待遇”原则,将会有更多国家向我们出口粮食,那时出口到中国的粮食就可能会远远的超出我们的需求,我们大量的土地就可能会被弃耕,我们的粮食安全就得不到保障了。

在这种背景下,我们就需要一个新的贸易体系——在WTO体系内,我们进口了1亿吨粮食,在RCEP体系下,我们对这个体系内的国家降低关税,再进口1亿吨粮食,这样正好能满足自己国家的需要,同时还不让国内土地荒废。

这就是RCEP和其它各种贸易组织不断诞生的第一个原因:WTO体系下各国降低关税的空间越来越小,已经不能满足世界经济发展的需要了。

当然还有第二个原因了。

 

第二,部分发达国家已经出现严重的逆全球化趋势,WTO面临巨大的风险;

大家都知道,不同的国家发展程度是不一样的:二战后,欧美等国家凭借以前的技术积累,很快便再次发展起来,但是还有很多国家发展的比较差。所以,发展中国家为了防止发达国家向本国倾销商品,彼此之间的关税非常高。

欧美发达国家为了向发展中国家出售高科技商品和其它优势商品,就给予了发展中国家很多的优惠,从而导致发达国家的财富不断的外流,使得本国经济遭受困难,于是它们逐渐的就不想要这个体系了……

这句话比较难懂,我们需要详细的给大家解释下。

比如,现在美国很发达,它想把汽车卖到中国,但是由于中国为了发展自己的汽车制造业,对美国汽车加征了巨额关税,美国汽车无法出口到中国。

这个时候,美国就对中国说:我对你开放服装、食品等市场,你把汽车关税降降……

中国寻思了下,觉得可以,于是就对美国说:你必须全部对我放开服装、玩具、彩电和食品等市场,关税直接降至0。然后呢,由于我们汽车制造发展还比较差,我不能一次性将关税大幅度下降,否则我的整个汽车制造业就完蛋了,我只能每年给你降10个点。

美国寻思了一下:服装、玩具那些低端制造业利润太低,本来美国人就不愿意干了,所以直接将关税降至0也没啥大不了的。但是,如果中国每年在汽车上降低10%的关税,那么我每年就能卖100万辆汽车给中国,这事可以做。

于是,双方就达成了协议。

但是,美国没有想到的是:中国的发展速度太快了,不但很快占领了美国中低端市场,而且很快向美国反出口汽车了。

以前我们为了防止美国汽车侵占中国市场,对美国汽车加征了100%的关税,按照协议,我们每年给美国降低10%的关税,但是没有想到到第五年的时候,我们的汽车发展到能向美国反出口了——虽然中国汽车的质量差,但是由于我们的汽车出口到美国没有关税,价格非常低,所以很多美国人反而开始买中国的汽车了。相反,由于中国对美国汽车还有50%的关税,美国汽车质量虽好,但是与中国廉价汽车相比,性价比反而低了,美国汽车在中国销量大降。

当然了,我们这个只是举例。事实上,日本汽车就是这么占领美国市场的,我们主要是在中低端制造上是这样占领美国市场的,包括彩电、冰箱等。

正是因为中国发展的太快了,远远的超出发达国家的预计,从而导致欧美国家在贸易上损失巨大,大量老百姓失去了制造业的高薪工作,从而导致发达国家逆全球化的现象比较严重——特朗普就是在这种背景下诞生的。

事实上,不仅仅是美国,欧洲很多国家逆全球化的现象也非常严重,甚至有一些发展中国家也想逆全球化。

所以,为了防止WTO体系的崩溃,很多国家也都在打造新的贸易体系。

也正是在这种背景下,RCEP才能加快成型。

全球最大自贸区正式生效,欧美打压中国的计划破产!

下面,我们就要说说RCEP达成的重要意义了。

RCEP协议达成以后,所有成员国之间90%的货物最终将实现0关税。

比如,在RCEP生效,降税完成后,中国与东盟、澳大利亚、新西兰之间的立即零关税比例将超过65%;

中国对韩国39%的商品立刻0关税,韩国对中国50%的商品立刻0关税;

中国对日本25%的商品立刻0关税,日本对中国57%的商品立刻0关税。然后逐年、逐步加大降税规模,最终86%的日本出口至中国的产品将实现零关税,同时中国出口至日本88%的产品将享受零关税待遇。

毫无疑问,这对区域内所有国家都是一个非常大的利好——由于关税降低,商品价格下降,销量必然要增加,各国经济都会出现比较大的增长。

但是,中国得到的好处无疑是更多的。

为什么这么说?

大家也知道,现在中国实力不断的增强,欧美等发达国家为了遏制中国的崛起,几乎无所不用其极,它们将病毒政治化、编造”新疆强迫劳动事件“等,其根本目的就是为了打压中国。

以后,中国企业想要把商品再出售到欧美国家的阻力是非常大的——现在,美国通胀已经创下了40年来的新高,在这么大压力下,拜登都没有取消对中国商品加征的关税。

根据最新数据:自从2018年特朗普对中国发动贸易战以来,中美两国关税水平大幅度增加。美国对从中国进口商品的平均关税从3%激增至约19%,而中国对自美国进口商品的平均关税从8%增至约21%。

说句实话,如果不是一场突如其来的疫情让美国经济崩溃,中国现在将面临巨大的困难:由于疫情,美国大量企业倒闭,工厂停产,美国人不得不购买中国商品,加征的关税几乎都由美国人承担了——美国进口商实际上承担了90%以上的美国关税成本。

就在这样的情况下,拜登都不取消特朗普时期对中国商品加征的巨额关税,由此可见——美国是铁了心的要发展自己的中低端制造的

试想:如果美国经济恢复了,你觉得中国商品还能卖到美国吗?

所以,在美国经济恢复之前,我们必须要找到替代市场,否则大量企业必将倒闭,必会对中国经济造成严重的冲击。

很显然,RCEP的正式生效为中国企业开辟了一个巨大的新兴市场,同时也为部分企业的转型再次争取到大量的时间。

老挝、柬埔寨、缅甸等国家还非常的贫穷,你想想,如果它们每家都需要一台彩电、一个冰箱、一个电脑,那么能够让中国企业生产制造多少年?这些国家完全可以替代美国市场。

那些国家想要获得中国生产制造的电视、冰箱和电脑等,就必须要把本国的资源和能源出售给中国,而开采资源和能源需要大量的电力、铁路、公路等,而它们并没有那个经济实力和技术能力,都得依靠中国,你说中国基建会在那些国家有多大的发展空间?

不仅仅是贸易和基础设施建设,在金融和服务上,中国的好处也非常的多。

大家都知道,在巨大的经济危机下,美国之所有敢肆无忌惮的印钱,其中最重要的一个原因就是:美元是霸权货币。

美元是霸权货币,国际贸易必须要使用美元,这样就使得美联储可以利用加息、降息、量化宽松、缩表等货币政策洗劫世界,但是RCEP生效后,很多国家与中国进行贸易合作的时候就可以不使用美元,这就降低了美元袭击世界的能力。

东盟国家之间有一个目标叫做“金融一体化”,很多东盟国家已经和中国开展了本币结算,不再需要美元——目前,东盟10国中,越南、老挝、印尼、泰国、马来西亚和缅甸等6个国家已经和中国开展了本币结算。

在中国强大的经济实力、政治实力和军事实力的支撑下,人民币的安全性要比那些国家的货币更加可靠,所以名义上是本币结算,但实际上却是促进了人民币国际化。

很显然,RCEP生效以后,中国和东盟等国家的贸易额会急剧增加,那些国家对人民币的需求必然会大幅增长;另外,东盟国家想要发展自己的基础设施建设,也必然要从中国获得资金和贷款,中国也必然会以人民币贷款给它们,这同样会加快人民币国际化。

所以,RCEP的生效不仅仅让欧美国家想要通过逆全球化打压中国的险恶用心破产,同时会对美元霸权发出一记强而有力的重击。

—–全文到此为止。

转自:https://mp.weixin.qq.com/s/OP72VWHCiX_u-3qF-kOhxg

五万字读懂c++

const作用

  1. 修饰变量,说明该变量不可以被改变;
  2. 修饰指针,分为指向常量的指针(pointer to const)和自身是常量的指针(常量指针,const pointer);
  3. 修饰引用,指向常量的引用(reference to const),用于形参类型,即避免了拷贝,又避免了函数对值的修改;
  4. 修饰成员函数,说明该成员函数内不能修改成员变量。

const 的指针与引用

  • 指针
    • 指向常量的指针(pointer to const)
    • 自身是常量的指针(常量指针,const pointer)
  • 引用
    • 指向常量的引用(reference to const)
    • 没有 const reference,因为引用只是对象的别名,引用不是对象,不能用 const 修饰

(为了方便记忆可以想成)被 const 修饰(在 const 后面)的值不可改变,如下文使用例子中的 p2p3

使用

const 使用

// 类class A{private:    const int a;                // 常对象成员,可以使用初始化列表或者类内初始化public:    // 构造函数    A() : a(0) { };    A(int x) : a(x) { };        // 初始化列表    // const可用于对重载函数的区分    int getValue();             // 普通成员函数    int getValue() const;       // 常成员函数,不得修改类中的任何数据成员的值};void function(){    // 对象    A b;                        // 普通对象,可以调用全部成员函数    const A a;                  // 常对象,只能调用常成员函数    const A *p = &a;            // 指针变量,指向常对象    const A &q = a;             // 指向常对象的引用    // 指针    char greeting[] = "Hello";    char* p1 = greeting;                // 指针变量,指向字符数组变量    const char* p2 = greeting;          // 指针变量,指向字符数组常量(const 后面是 char,说明指向的字符(char)不可改变)    char* const p3 = greeting;          // 自身是常量的指针,指向字符数组变量(const 后面是 p3,说明 p3 指针自身不可改变)    const char* const p4 = greeting;    // 自身是常量的指针,指向字符数组常量}// 函数void function1(const int Var);           // 传递过来的参数在函数内不可变void function2(const char* Var);         // 参数指针所指内容为常量void function3(char* const Var);         // 参数指针为常量void function4(const int& Var);          // 引用参数在函数内为常量// 函数返回值const int function5();      // 返回一个常数const int* function6();     // 返回一个指向常量的指针变量,使用:const int *p = function6();int* const function7();     // 返回一个指向变量的常指针,使用:int* const p = function7();

宏定义 #define 和 const 常量

宏定义 #defineconst 常量
宏定义,相当于字符替换常量声明
预处理器处理编译器处理
无类型安全检查有类型安全检查
不分配内存要分配内存
存储在代码段存储在数据段
可通过 #undef 取消不可取消

static

作用

  1. 修饰普通变量,修改变量的存储区域和生命周期,使变量存储在静态区,在 main 函数运行前就分配了空间,如果有初始值就用初始值初始化它,如果没有初始值系统用默认值初始化它。
  2. 修饰普通函数,表明函数的作用范围,仅在定义该函数的文件内才能使用。在多人开发项目时,为了防止与他人命名空间里的函数重名,可以将函数定位为 static。
  3. 修饰成员变量,修饰成员变量使所有的对象只保存一个该变量,而且不需要生成对象就可以访问该成员。
  4. 修饰成员函数,修饰成员函数使得不需要生成对象就可以访问该函数,但是在 static 函数内不能访问非静态成员。

this 指针

  1. this 指针是一个隐含于每一个非静态成员函数中的特殊指针。它指向调用该成员函数的那个对象。
  2. 当对一个对象调用成员函数时,编译程序先将对象的地址赋给 this 指针,然后调用成员函数,每次成员函数存取数据成员时,都隐式使用 this 指针。
  3. 当一个成员函数被调用时,自动向它传递一个隐含的参数,该参数是一个指向这个成员函数所在的对象的指针。
  4. this 指针被隐含地声明为: ClassName *const this,这意味着不能给 this 指针赋值;在 ClassName 类的 const 成员函数中,this 指针的类型为:const ClassName* const,这说明不能对 this 指针所指向的这种对象是不可修改的(即不能对这种对象的数据成员进行赋值操作);
  5. this 并不是一个常规变量,而是个右值,所以不能取得 this 的地址(不能 &this)。
  6. 在以下场景中,经常需要显式引用this
    指针:
    1. 为实现对象的链式引用;
    2. 为避免对同一对象进行赋值操作;
    3. 在实现一些数据结构时,如 list

inline 内联函数

特征

  • 相当于把内联函数里面的内容写在调用内联函数处;
  • 相当于不用执行进入函数的步骤,直接执行函数体;
  • 相当于宏,却比宏多了类型检查,真正具有函数特性;
  • 编译器一般不内联包含循环、递归、switch 等复杂操作的内联函数;
  • 在类声明中定义的函数,除了虚函数的其他函数都会自动隐式地当成内联函数。

使用

inline 使用

// 声明1(加 inline,建议使用)inline int functionName(int first, int second,...);// 声明2(不加 inline)int functionName(int first, int second,...);// 定义inline int functionName(int first, int second,...) {/****/};// 类内定义,隐式内联class A {    int doA() { return 0; }         // 隐式内联}// 类外定义,需要显式内联class A {    int doA();}inline int A::doA() { return 0; }   // 需要显式内联

编译器对 inline 函数的处理步骤

  1. 将 inline 函数体复制到 inline 函数调用点处;
  2. 为所用 inline 函数中的局部变量分配内存空间;
  3. 将 inline 函数的的输入参数和返回值映射到调用方法的局部变量空间中;
  4. 如果 inline 函数有多个返回点,将其转变为 inline 函数代码块末尾的分支(使用 GOTO)。

优缺点

优点

  1. 内联函数同宏函数一样将在被调用处进行代码展开,省去了参数压栈、栈帧开辟与回收,结果返回等,从而提高程序运行速度。
  2. 内联函数相比宏函数来说,在代码展开时,会做安全检查或自动类型转换(同普通函数),而宏定义则不会。
  3. 在类中声明同时定义的成员函数,自动转化为内联函数,因此内联函数可以访问类的成员变量,宏定义则不能。
  4. 内联函数在运行时可调试,而宏定义不可以。

缺点

  1. 代码膨胀。内联是以代码膨胀(复制)为代价,消除函数调用带来的开销。如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。
  2. inline 函数无法随着函数库升级而升级。inline函数的改变需要重新编译,不像 non-inline 可以直接链接。
  3. 是否内联,程序员不可控。内联函数只是对编译器的建议,是否对函数内联,决定权在于编译器。

虚函数(virtual)可以是内联函数(inline)吗?

Are “inline virtual” member functions ever actually “inlined”?

  • 虚函数可以是内联函数,内联是可以修饰虚函数的,但是当虚函数表现多态性的时候不能内联。
  • 内联是在编译器建议编译器内联,而虚函数的多态性在运行期,编译器无法知道运行期调用哪个代码,因此虚函数表现为多态性时(运行期)不可以内联。
  • inline virtual 唯一可以内联的时候是:编译器知道所调用的对象是哪个类(如 Base::who()),这只有在编译器具有实际对象而不是对象的指针或引用时才会发生。

虚函数内联使用

#include <iostream>  using namespace std;class Base{public: inline virtual void who() {  cout << "I am Base\n"; } virtual ~Base() {}};class Derived : public Base{public: inline void who()  // 不写inline时隐式内联 {  cout << "I am Derived\n"; }};int main(){ // 此处的虚函数 who(),是通过类(Base)的具体对象(b)来调用的,编译期间就能确定了,所以它可以是内联的,但最终是否内联取决于编译器。  Base b; b.who(); // 此处的虚函数是通过指针调用的,呈现多态性,需要在运行时期间才能确定,所以不能为内联。   Base *ptr = new Derived(); ptr->who(); // 因为Base有虚析构函数(virtual ~Base() {}),所以 delete 时,会先调用派生类(Derived)析构函数,再调用基类(Base)析构函数,防止内存泄漏。 delete ptr; ptr = nullptr; system("pause"); return 0;} 

volatile

volatile int i = 10; 
  • volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素(操作系统、硬件、其它线程等)更改。所以使用 volatile 告诉编译器不应对这样的对象进行优化。
  • volatile 关键字声明的变量,每次访问时都必须从内存中取出值(没有被 volatile 修饰的变量,可能由于编译器的优化,从 CPU 寄存器中取值)
  • const 可以是 volatile (如只读的状态寄存器)
  • 指针可以是 volatile

assert()

断言,是宏,而非函数。assert 宏的原型定义在 <assert.h>(C)、<cassert>(C++)中,其作用是如果它的条件返回错误,则终止程序执行。可以通过定义 NDEBUG 来关闭 assert,但是需要在源代码的开头,include <assert.h> 之前。

assert() 使用

#define NDEBUG          // 加上这行,则 assert 不可用#include <assert.h>assert( p != NULL );    // assert 不可用

sizeof()

  • sizeof 对数组,得到整个数组所占空间大小。
  • sizeof 对指针,得到指针本身所占空间大小。

#pragma pack(n)

设定结构体、联合以及类成员变量以 n 字节方式对齐

#pragma pack(n) 使用

#pragma pack(push)  // 保存对齐状态#pragma pack(4)     // 设定为 4 字节对齐struct test{    char m1;    double m4;    int m3;};#pragma pack(pop)   // 恢复对齐状态

位域

Bit mode: 2;    // mode 占 2 位

类可以将其(非静态)数据成员定义为位域(bit-field),在一个位域中含有一定数量的二进制位。当一个程序需要向其他程序或硬件设备传递二进制数据时,通常会用到位域。

  • 位域在内存中的布局是与机器有关的
  • 位域的类型必须是整型或枚举类型,带符号类型中的位域的行为将因具体实现而定
  • 取地址运算符(&)不能作用于位域,任何指针都无法指向类的位域

extern “C”

  • 被 extern 限定的函数或变量是 extern 类型的
  • 被 extern "C" 修饰的变量和函数是按照 C 语言方式编译和链接的

extern "C" 的作用是让 C++ 编译器将 extern "C" 声明的代码当作 C 语言代码处理,可以避免 C++ 因符号修饰导致代码不能和C语言库中的符号进行链接的问题。

extern “C” 使用

#ifdef __cplusplusextern "C" {#endifvoid *memset(void *, int, size_t);#ifdef __cplusplus}#endif

struct 和 typedef struct

C 中

// ctypedef struct Student {    int age; } S;

等价于

// cstruct Student {     int age; };typedef struct Student S;

此时 S 等价于 struct Student,但两个标识符名称空间不相同。

另外还可以定义与 struct Student 不冲突的 void Student() {}

C++ 中

由于编译器定位符号的规则(搜索规则)改变,导致不同于C语言。

一、如果在类标识符空间定义了 struct Student {...};,使用 Student me; 时,编译器将搜索全局标识符表,Student 未找到,则在类标识符内搜索。

即表现为可以使用 Student 也可以使用 struct Student,如下:

// cppstruct Student {     int age; };void f( Student me );       // 正确,"struct" 关键字可省略

二、若定义了与 Student 同名函数之后,则 Student 只代表函数,不代表结构体,如下:

typedef struct Student {     int age; } S;void Student() {}           // 正确,定义后 "Student" 只代表此函数//void S() {}               // 错误,符号 "S" 已经被定义为一个 "struct Student" 的别名int main() {    Student();     struct Student me;      // 或者 "S me";    return 0;}

C++ 中 struct 和 class

总的来说,struct 更适合看成是一个数据结构的实现体,class 更适合看成是一个对象的实现体。

区别

  • 最本质的一个区别就是默认的访问控制
    1. 默认的继承访问权限。struct 是 public 的,class 是 private 的。
    2. struct 作为数据结构的实现体,它默认的数据访问控制是 public 的,而 class 作为对象的实现体,它默认的成员变量访问控制是 private 的。

union 联合

联合(union)是一种节省空间的特殊的类,一个 union 可以有多个数据成员,但是在任意时刻只有一个数据成员可以有值。当某个成员被赋值后其他成员变为未定义状态。联合有如下特点:

  • 默认访问控制符为 public
  • 可以含有构造函数、析构函数
  • 不能含有引用类型的成员
  • 不能继承自其他类,不能作为基类
  • 不能含有虚函数
  • 匿名 union 在定义所在作用域可直接访问 union 成员
  • 匿名 union 不能包含 protected 成员或 private 成员
  • 全局匿名联合必须是静态(static)的

union 使用

#include<iostream>union UnionTest {    UnionTest() : i(10) {};    int i;    double d;};static union {    int i;    double d;};int main() {    UnionTest u;    union {        int i;        double d;    };    std::cout << u.i << std::endl;  // 输出 UnionTest 联合的 10    ::i = 20;    std::cout << ::i << std::endl;  // 输出全局静态匿名联合的 20    i = 30;    std::cout << i << std::endl;    // 输出局部匿名联合的 30    return 0;}

C 实现 C++ 类

C 实现 C++ 的面向对象特性(封装、继承、多态)

  • 封装:使用函数指针把属性与方法封装到结构体中
  • 继承:结构体嵌套
  • 多态:父类与子类方法的函数指针不同

[Can you write object-oriented code in C? closed]

explicit(显式)关键字

  • explicit 修饰构造函数时,可以防止隐式转换和复制初始化
  • explicit 修饰转换函数时,可以防止隐式转换,但 按语境转换 除外

explicit 使用

struct A{ A(int) { } operator bool() const { return true; }};struct B{ explicit B(int) {} explicit operator bool() const { return true; }};void doA(A a) {}void doB(B b) {}int main(){ A a1(1);  // OK:直接初始化 A a2 = 1;  // OK:复制初始化 A a3{ 1 };  // OK:直接列表初始化 A a4 = { 1 };  // OK:复制列表初始化 A a5 = (A)1;  // OK:允许 static_cast 的显式转换  doA(1);   // OK:允许从 int 到 A 的隐式转换 if (a1);  // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换 bool a6(a1);  // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换 bool a7 = a1;  // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换 bool a8 = static_cast<bool>(a1);  // OK :static_cast 进行直接初始化 B b1(1);  // OK:直接初始化 B b2 = 1;  // 错误:被 explicit 修饰构造函数的对象不可以复制初始化 B b3{ 1 };  // OK:直接列表初始化 B b4 = { 1 };  // 错误:被 explicit 修饰构造函数的对象不可以复制列表初始化 B b5 = (B)1;  // OK:允许 static_cast 的显式转换 doB(1);   // 错误:被 explicit 修饰构造函数的对象不可以从 int 到 B 的隐式转换 if (b1);  // OK:被 explicit 修饰转换函数 B::operator bool() 的对象可以从 B 到 bool 的按语境转换 bool b6(b1);  // OK:被 explicit 修饰转换函数 B::operator bool() 的对象可以从 B 到 bool 的按语境转换 bool b7 = b1;  // 错误:被 explicit 修饰转换函数 B::operator bool() 的对象不可以隐式转换 bool b8 = static_cast<bool>(b1);  // OK:static_cast 进行直接初始化 return 0;}

friend 友元类和友元函数

  • 能访问私有成员
  • 破坏封装性
  • 友元关系不可传递
  • 友元关系的单向性
  • 友元声明的形式及数量不受限制

using

using 声明

一条 using 声明 语句一次只引入命名空间的一个成员。它使得我们可以清楚知道程序中所引用的到底是哪个名字。如:

using namespace_name::name;

构造函数的 using 声明

在 C++11 中,派生类能够重用其直接基类定义的构造函数。

class Derived : Base {public:    using Base::Base;    /* ... */};

如上 using 声明,对于基类的每个构造函数,编译器都生成一个与之对应(形参列表完全相同)的派生类构造函数。生成如下类型构造函数:

Derived(parms) : Base(args) { }

using 指示

using 指示 使得某个特定命名空间中所有名字都可见,这样我们就无需再为它们添加任何前缀限定符了。如:

using namespace_name name;

尽量少使用 using 指示 污染命名空间

一般说来,使用 using 命令比使用 using 编译命令更安全,这是由于它只导入了指定的名称。如果该名称与局部名称发生冲突,编译器将发出指示。using编译命令导入所有的名称,包括可能并不需要的名称。如果与局部名称发生冲突,则局部名称将覆盖名称空间版本,而编译器并不会发出警告。另外,名称空间的开放性意味着名称空间的名称可能分散在多个地方,这使得难以准确知道添加了哪些名称。

using 使用

尽量少使用 using 指示

using namespace std;

应该多使用 using 声明

int x;std::cin >> x ;std::cout << x << std::endl;

或者

using std::cin;using std::cout;using std::endl;int x;cin >> x;cout << x << endl;

:: 范围解析运算符

分类

  1. 全局作用域符(::name):用于类型名称(类、类成员、成员函数、变量等)前,表示作用域为全局命名空间
  2. 类作用域符(class::name):用于表示指定类型的作用域范围是具体某个类的
  3. 命名空间作用域符(namespace::name):用于表示指定类型的作用域范围是具体某个命名空间的

:: 使用

int count = 11;         // 全局(::)的 countclass A {public: static int count;   // 类 A 的 count(A::count)};int A::count = 21;void fun(){ int count = 31;     // 初始化局部的 count 为 31 count = 32;         // 设置局部的 count 的值为 32}int main() { ::count = 12;       // 测试 1:设置全局的 count 的值为 12 A::count = 22;      // 测试 2:设置类 A 的 count 为 22 fun();          // 测试 3 return 0;}

enum 枚举类型

限定作用域的枚举类型

enum class open_modes { input, output, append };

不限定作用域的枚举类型

enum color { red, yellow, green };enum { floatPrec = 6, doublePrec = 10 };

decltype

decltype 关键字用于检查实体的声明类型或表达式的类型及值分类。语法:

decltype ( expression )

decltype 使用

// 尾置返回允许我们在参数列表之后声明返回类型template <typename It>auto fcn(It beg, It end) -> decltype(*beg){    // 处理序列    return *beg;    // 返回序列中一个元素的引用}// 为了使用模板参数成员,必须用 typenametemplate <typename It>auto fcn2(It beg, It end) -> typename remove_reference<decltype(*beg)>::type{    // 处理序列    return *beg;    // 返回序列中一个元素的拷贝}

引用

左值引用

常规引用,一般表示对象的身份。

右值引用

右值引用就是必须绑定到右值(一个临时对象、将要销毁的对象)的引用,一般表示对象的值。

右值引用可实现转移语义(Move Sementics)和精确传递(Perfect Forwarding),它的主要目的有两个方面:

  • 消除两个对象交互时不必要的对象拷贝,节省运算存储资源,提高效率。
  • 能够更简洁明确地定义泛型函数。

引用折叠

  • X& &X& &&X&& & 可折叠成 X&
  • X&& && 可折叠成 X&&

  • 宏定义可以实现类似于函数的功能,但是它终归不是函数,而宏定义中括弧中的“参数”也不是真的参数,在宏展开的时候对 “参数” 进行的是一对一的替换。

成员初始化列表

好处

  • 更高效:少了一次调用默认构造函数的过程。
  • 有些场合必须要用初始化列表:
    1. 常量成员,因为常量只能初始化不能赋值,所以必须放在初始化列表里面
    2. 引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要写在初始化列表里面
    3. 没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化

initializer_list 列表初始化

用花括号初始化器列表初始化一个对象,其中对应构造函数接受一个 std::initializer_list 参数.

initializer_list 使用

#include <iostream>#include <vector>#include <initializer_list> template <class T>struct S {    std::vector<T> v;    S(std::initializer_list<T> l) : v(l) {         std::cout << "constructed with a " << l.size() << "-element list\n";    }    void append(std::initializer_list<T> l) {        v.insert(v.end(), l.begin(), l.end());    }    std::pair<const T*, std::size_t> c_arr() const {        return {&v[0], v.size()};  // 在 return 语句中复制列表初始化                                   // 这不使用 std::initializer_list    }}; template <typename T>void templated_fn(T) {} int main(){    S<int> s = {1, 2, 3, 4, 5}; // 复制初始化    s.append({6, 7, 8});      // 函数调用中的列表初始化     std::cout << "The vector size is now " << s.c_arr().second << " ints:\n";     for (auto n : s.v)        std::cout << n << ' ';    std::cout << '\n';     std::cout << "Range-for over brace-init-list: \n";     for (int x : {-1, -2, -3}) // auto 的规则令此带范围 for 工作        std::cout << x << ' ';    std::cout << '\n';     auto al = {10, 11, 12};   // auto 的特殊规则     std::cout << "The list bound to auto has size() = " << al.size() << '\n'; //    templated_fn({1, 2, 3}); // 编译错误!“ {1, 2, 3} ”不是表达式,                             // 它无类型,故 T 无法推导    templated_fn<std::initializer_list<int>>({1, 2, 3}); // OK    templated_fn<std::vector<int>>({1, 2, 3});           // 也 OK}

面向对象

面向对象程序设计(Object-oriented programming,OOP)是种具有对象概念的程序编程典范,同时也是一种程序开发的抽象方针。

面向对象三大特征 —— 封装、继承、多态

封装

把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。关键字:public, protected, private。不写默认为 private。

  • public 成员:可以被任意实体访问
  • protected 成员:只允许被子类及本类的成员函数访问
  • private 成员:只允许被本类的成员函数、友元类或友元函数访问

继承

  • 基类(父类)——> 派生类(子类)

多态

  • 多态,即多种状态(形态)。简单来说,我们可以将多态定义为消息以多种形式显示的能力。
  • 多态是以封装和继承为基础的。
  • C++ 多态分类及实现:
    1. 重载多态(Ad-hoc Polymorphism,编译期):函数重载、运算符重载
    2. 子类型多态(Subtype Polymorphism,运行期):虚函数
    3. 参数多态性(Parametric Polymorphism,编译期):类模板、函数模板
    4. 强制多态(Coercion Polymorphism,编译期/运行期):基本类型转换、自定义类型转换

The Four Polymorphisms in C++

静态多态(编译期/早绑定)

函数重载

class A{public:    void do(int a);    void do(int a, int b);};

动态多态(运行期期/晚绑定)

  • 虚函数:用 virtual 修饰成员函数,使其成为虚函数
  • 动态绑定:当使用基类的引用或指针调用一个虚函数时将发生动态绑定

注意:

  • 可以将派生类的对象赋值给基类的指针或引用,反之不可
  • 普通函数(非类成员函数)不能是虚函数
  • 静态函数(static)不能是虚函数
  • 构造函数不能是虚函数(因为在调用构造函数时,虚表指针并没有在对象的内存空间中,必须要构造函数调用完成后才会形成虚表指针)
  • 内联函数不能是表现多态性时的虚函数,解释见:虚函数(virtual)可以是内联函数(inline)吗?

动态多态使用

class Shape                     // 形状类{public:    virtual double calcArea()    {        ...    }    virtual ~Shape();};class Circle : public Shape     // 圆形类{public:    virtual double calcArea();    ...};class Rect : public Shape       // 矩形类{public:    virtual double calcArea();    ...};int main(){    Shape * shape1 = new Circle(4.0);    Shape * shape2 = new Rect(5.0, 6.0);    shape1->calcArea();         // 调用圆形类里面的方法    shape2->calcArea();         // 调用矩形类里面的方法    delete shape1;    shape1 = nullptr;    delete shape2;    shape2 = nullptr;    return 0;}

虚析构函数

虚析构函数是为了解决基类的指针指向派生类对象,并用基类的指针删除派生类对象。

虚析构函数使用

class Shape{public:    Shape();                    // 构造函数不能是虚函数    virtual double calcArea();    virtual ~Shape();           // 虚析构函数};class Circle : public Shape     // 圆形类{public:    virtual double calcArea();    ...};int main(){    Shape * shape1 = new Circle(4.0);    shape1->calcArea();        delete shape1;  // 因为Shape有虚析构函数,所以delete释放内存时,先调用子类析构函数,再调用基类析构函数,防止内存泄漏。    shape1 = NULL;    return 0;}

纯虚函数

纯虚函数是一种特殊的虚函数,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。

virtual int A() = 0;

虚函数、纯虚函数

  • 类里如果声明了虚函数,这个函数是实现的,哪怕是空实现,它的作用就是为了能让这个函数在它的子类里面可以被覆盖(override),这样的话,编译器就可以使用后期绑定来达到多态了。纯虚函数只是一个接口,是个函数的声明而已,它要留到子类里去实现。
  • 虚函数在子类里面可以不重写;但纯虚函数必须在子类实现才可以实例化子类。
  • 虚函数的类用于 “实作继承”,继承接口的同时也继承了父类的实现。纯虚函数关注的是接口的统一性,实现由子类完成。
  • 带纯虚函数的类叫抽象类,这种类不能直接生成对象,而只有被继承,并重写其虚函数后,才能使用。抽象类被继承后,子类可以继续是抽象类,也可以是普通类。
  • 虚基类是虚继承中的基类,具体见下文虚继承。

CSDN . C++ 中的虚函数、纯虚函数区别和联系

虚函数指针、虚函数表

  • 虚函数指针:在含有虚函数类的对象中,指向虚函数表,在运行时确定。
  • 虚函数表:在程序只读数据段(.rodata section,见:目标文件存储结构),存放虚函数指针,如果派生类实现了基类的某个虚函数,则在虚表中覆盖原本基类的那个虚函数指针,在编译时根据类的声明创建。

C++中的虚函数(表)实现机制以及用C语言对其进行的模拟实现

虚继承

虚继承用于解决多继承条件下的菱形继承问题(浪费存储空间、存在二义性)。

底层实现原理与编译器相关,一般通过虚基类指针和虚基类表实现,每个虚继承的子类都有一个虚基类指针(占用一个指针的存储空间,4字节)和虚基类表(不占用类对象的存储空间)(需要强调的是,虚基类依旧会在子类里面存在拷贝,只是仅仅最多存在一份而已,并不是不在子类里面了);当虚继承的子类被当做父类继承时,虚基类指针也会被继承。

实际上,vbptr 指的是虚基类表指针(virtual base table pointer),该指针指向了一个虚基类表(virtual table),虚表中记录了虚基类与本类的偏移地址;通过偏移地址,这样就找到了虚基类成员,而虚继承也不用像普通多继承那样维持着公共基类(虚基类)的两份同样的拷贝,节省了存储空间。

虚继承、虚函数

  • 相同之处:都利用了虚指针(均占用类的存储空间)和虚表(均不占用类的存储空间)
  • 不同之处:
    • 虚函数不占用存储空间
    • 虚函数表存储的是虚函数地址
    • 虚基类依旧存在继承类中,只占用存储空间
    • 虚基类表存储的是虚基类相对直接继承类的偏移
    • 虚继承
    • 虚函数

模板类、成员模板、虚函数

  • 模板类中可以使用虚函数
  • 一个类(无论是普通类还是类模板)的成员模板(本身是模板的成员函数)不能是虚函数

抽象类、接口类、聚合类

  • 抽象类:含有纯虚函数的类
  • 接口类:仅含有纯虚函数的抽象类
  • 聚合类:用户可以直接访问其成员,并且具有特殊的初始化语法形式。满足如下特点:
    • 所有成员都是 public
    • 没有定义任何构造函数
    • 没有类内初始化
    • 没有基类,也没有 virtual 函数

内存分配和管理

malloc、calloc、realloc、alloca

  1. malloc:申请指定字节数的内存。申请到的内存中的初始值不确定。
  2. calloc:为指定长度的对象,分配能容纳其指定个数的内存。申请到的内存的每一位(bit)都初始化为 0。
  3. realloc:更改以前分配的内存长度(增加或减少)。当增加长度时,可能需将以前分配区的内容移到另一个足够大的区域,而新增区域内的初始值则不确定。
  4. alloca:在栈上申请内存。程序在出栈的时候,会自动释放内存。但是需要注意的是,alloca 不具可移植性, 而且在没有传统堆栈的机器上很难实现。alloca 不宜使用在必须广泛移植的程序中。C99 中支持变长数组 (VLA),可以用来替代 alloca。

malloc、free

用于分配、释放内存

malloc、free 使用

申请内存,确认是否申请成功

char *str = (char*) malloc(100);assert(str != nullptr);

释放内存后指针置空

free(p); p = nullptr;

new、delete

  1. new / new[]:完成两件事,先底层调用 malloc 分配了内存,然后调用构造函数(创建对象)。
  2. delete/delete[]:也完成两件事,先调用析构函数(清理资源),然后底层调用 free 释放空间。
  3. new 在申请内存时会自动计算所需字节数,而 malloc 则需我们自己输入申请内存空间的字节数。

new、delete 使用

申请内存,确认是否申请成功

int main(){    T* t = new T();     // 先内存分配 ,再构造函数    delete t;           // 先析构函数,再内存释放    return 0;}

定位 new

定位 new(placement new)允许我们向 new 传递额外的地址参数,从而在预先指定的内存区域创建对象。

new (place_address) typenew (place_address) type (initializers)new (place_address) type [size]new (place_address) type [size] { braced initializer list }
  • place_address 是个指针
  • initializers 提供一个(可能为空的)以逗号分隔的初始值列表

delete this 合法吗?

Is it legal (and moral) for a member function to say delete this?

合法,但:

  1. 必须保证 this 对象是通过 new(不是 new[]、不是 placement new、不是栈上、不是全局、不是其他对象成员)分配的
  2. 必须保证调用 delete this 的成员函数是最后一个调用 this 的成员函数
  3. 必须保证成员函数的 delete this后面没有调用 this 了
  4. 必须保证 delete this 后没有人使用了

如何定义一个只能在堆上(栈上)生成对象的类?

如何定义一个只能在堆上(栈上)生成对象的类?

只能在堆上

方法:将析构函数设置为私有

原因:C++ 是静态绑定语言,编译器管理栈上对象的生命周期,编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性。若析构函数不可访问,则不能在栈上创建对象。

只能在栈上

方法:将 new 和 delete 重载为私有

原因:在堆上生成对象,使用 new 关键词操作,其过程分为两阶段:第一阶段,使用 new 在堆上寻找可用内存,分配给对象;第二阶段,调用构造函数生成对象。将 new 操作设置为私有,那么第一阶段就无法完成,就不能够在堆上生成对象。

智能指针

C++ 标准库(STL)中

头文件:#include <memory>

C++ 98

std::auto_ptr<std::string> ps (new std::string(str));

C++ 11

  1. shared_ptr
  2. unique_ptr
  3. weak_ptr
  4. auto_ptr(被 C++11 弃用)
  • Class shared_ptr 实现共享式拥有(shared ownership)概念。多个智能指针指向相同对象,该对象和其相关资源会在 “最后一个 reference 被销毁” 时被释放。为了在结构较复杂的情景中执行上述工作,标准库提供 weak_ptr、bad_weak_ptr 和 enable_shared_from_this 等辅助类。
  • Class unique_ptr 实现独占式拥有(exclusive ownership)或严格拥有(strict ownership)概念,保证同一时间内只有一个智能指针可以指向该对象。你可以移交拥有权。它对于避免内存泄漏(resource leak)——如 new 后忘记 delete ——特别有用。
shared_ptr

多个智能指针可以共享同一个对象,对象的最末一个拥有着有责任销毁对象,并清理与该对象相关的所有资源。

  • 支持定制型删除器(custom deleter),可防范 Cross-DLL 问题(对象在动态链接库(DLL)中被 new 创建,却在另一个 DLL 内被 delete 销毁)、自动解除互斥锁
weak_ptr

weak_ptr 允许你共享但不拥有某对象,一旦最末一个拥有该对象的智能指针失去了所有权,任何 weak_ptr 都会自动成空(empty)。因此,在 default 和 copy 构造函数之外,weak_ptr 只提供 “接受一个 shared_ptr” 的构造函数。

  • 可打破环状引用(cycles of references,两个其实已经没有被使用的对象彼此互指,使之看似还在 “被使用” 的状态)的问题
unique_ptr

unique_ptr 是 C++11 才开始提供的类型,是一种在异常时可以帮助避免资源泄漏的智能指针。采用独占式拥有,意味着可以确保一个对象和其相应的资源同一时间只被一个 pointer 拥有。一旦拥有着被销毁或编程 empty,或开始拥有另一个对象,先前拥有的那个对象就会被销毁,其任何相应资源亦会被释放。

  • unique_ptr 用于取代 auto_ptr
auto_ptr

被 c++11 弃用,原因是缺乏语言特性如 “针对构造和赋值” 的 std::move 语义,以及其他瑕疵。

auto_ptr 与 unique_ptr 比较
  • auto_ptr 可以赋值拷贝,复制拷贝后所有权转移;unqiue_ptr 无拷贝赋值语义,但实现了move 语义;
  • auto_ptr 对象不能管理数组(析构调用 delete),unique_ptr 可以管理数组(析构调用 delete[] );

强制类型转换运算符

MSDN . 强制转换运算符

static_cast

  • 用于非多态类型的转换
  • 不执行运行时类型检查(转换安全性不如 dynamic_cast)
  • 通常用于转换数值数据类型(如 float -> int)
  • 可以在整个类层次结构中移动指针,子类转化为父类安全(向上转换),父类转化为子类不安全(因为子类可能有不在父类的字段或方法)

向上转换是一种隐式转换。

dynamic_cast

  • 用于多态类型的转换
  • 执行行运行时类型检查
  • 只适用于指针或引用
  • 对不明确的指针的转换将失败(返回 nullptr),但不引发异常
  • 可以在整个类层次结构中移动指针,包括向上转换、向下转换

const_cast

  • 用于删除 const、volatile 和 __unaligned 特性(如将 const int 类型转换为 int 类型 )

reinterpret_cast

  • 用于位的简单重新解释
  • 滥用 reinterpret_cast 运算符可能很容易带来风险。除非所需转换本身是低级别的,否则应使用其他强制转换运算符之一。
  • 允许将任何指针转换为任何其他指针类型(如 char* 到 int* 或 One_class* 到 Unrelated_class* 之类的转换,但其本身并不安全)
  • 也允许将任何整数类型转换为任何指针类型以及反向转换。
  • reinterpret_cast 运算符不能丢掉 const、volatile 或 __unaligned 特性。
  • reinterpret_cast 的一个实际用途是在哈希函数中,即,通过让两个不同的值几乎不以相同的索引结尾的方式将值映射到索引。

bad_cast

  • 由于强制转换为引用类型失败,dynamic_cast 运算符引发 bad_cast 异常。

bad_cast 使用

try {      Circle& ref_circle = dynamic_cast<Circle&>(ref_shape);   }  catch (bad_cast b) {      cout << "Caught: " << b.what();  } 

运行时类型信息 (RTTI)

dynamic_cast

  • 用于多态类型的转换

typeid

  • typeid 运算符允许在运行时确定对象的类型
  • type_id 返回一个 type_info 对象的引用
  • 如果想通过基类的指针获得派生类的数据类型,基类必须带有虚函数
  • 只能获取对象的实际类型

type_info

  • type_info 类描述编译器在程序中生成的类型信息。此类的对象可以有效存储指向类型的名称的指针。type_info 类还可存储适合比较两个类型是否相等或比较其排列顺序的编码值。类型的编码规则和排列顺序是未指定的,并且可能因程序而异。
  • 头文件:typeinfo

typeid、type_info 使用

#include <iostream>using namespace std;class Flyable                       // 能飞的{public:    virtual void takeoff() = 0;     // 起飞    virtual void land() = 0;        // 降落};class Bird : public Flyable         // 鸟{public:    void foraging() {...}           // 觅食    virtual void takeoff() {...}    virtual void land() {...}    virtual ~Bird(){}};class Plane : public Flyable        // 飞机{public:    void carry() {...}              // 运输    virtual void takeoff() {...}    virtual void land() {...}};class type_info{public:    const char* name() const;    bool operator == (const type_info & rhs) const;    bool operator != (const type_info & rhs) const;    int before(const type_info & rhs) const;    virtual ~type_info();private:    ...};void doSomething(Flyable *obj)                 // 做些事情{    obj->takeoff();    cout << typeid(*obj).name() << endl;        // 输出传入对象类型("class Bird" or "class Plane")    if(typeid(*obj) == typeid(Bird))            // 判断对象类型    {        Bird *bird = dynamic_cast<Bird *>(obj); // 对象转化        bird->foraging();    }    obj->land();}int main(){ Bird *b = new Bird(); doSomething(b); delete b; b = nullptr; return 0;}

⭐️ Effective

Effective C++

  1. 视 C++ 为一个语言联邦(C、Object-Oriented C++、Template C++、STL)
  2. 宁可以编译器替换预处理器(尽量以 constenuminline 替换 #define
  3. 尽可能使用 const
  4. 确定对象被使用前已先被初始化(构造时赋值(copy 构造函数)比 default 构造后赋值(copy assignment)效率高)
  5. 了解 C++ 默默编写并调用哪些函数(编译器暗自为 class 创建 default 构造函数、copy 构造函数、copy assignment 操作符、析构函数)
  6. 若不想使用编译器自动生成的函数,就应该明确拒绝(将不想使用的成员函数声明为 private,并且不予实现)
  7. 为多态基类声明 virtual 析构函数(如果 class 带有任何 virtual 函数,它就应该拥有一个 virtual 析构函数)
  8. 别让异常逃离析构函数(析构函数应该吞下不传播异常,或者结束程序,而不是吐出异常;如果要处理异常应该在非析构的普通函数处理)
  9. 绝不在构造和析构过程中调用 virtual 函数(因为这类调用从不下降至 derived class)
  10. 令 operator= 返回一个 reference to *this (用于连锁赋值)
  11. 在 operator= 中处理 “自我赋值”
  12. 赋值对象时应确保复制 “对象内的所有成员变量” 及 “所有 base class 成分”(调用基类复制构造函数)
  13. 以对象管理资源(资源在构造函数获得,在析构函数释放,建议使用智能指针,资源取得时机便是初始化时机(Resource Acquisition Is Initialization,RAII))
  14. 在资源管理类中小心 copying 行为(普遍的 RAII class copying 行为是:抑制 copying、引用计数、深度拷贝、转移底部资源拥有权(类似 auto_ptr))
  15. 在资源管理类中提供对原始资源(raw resources)的访问(对原始资源的访问可能经过显式转换或隐式转换,一般而言显示转换比较安全,隐式转换对客户比较方便)
  16. 成对使用 new 和 delete 时要采取相同形式(new 中使用 [] 则 delete []new 中不使用 [] 则 delete
  17. 以独立语句将 newed 对象存储于(置入)智能指针(如果不这样做,可能会因为编译器优化,导致难以察觉的资源泄漏)
  18. 让接口容易被正确使用,不易被误用(促进正常使用的办法:接口的一致性、内置类型的行为兼容;阻止误用的办法:建立新类型,限制类型上的操作,约束对象值、消除客户的资源管理责任)
  19. 设计 class 犹如设计 type,需要考虑对象创建、销毁、初始化、赋值、值传递、合法值、继承关系、转换、一般化等等。
  20. 宁以 pass-by-reference-to-const 替换 pass-by-value (前者通常更高效、避免切割问题(slicing problem),但不适用于内置类型、STL迭代器、函数对象)
  21. 必须返回对象时,别妄想返回其 reference(绝不返回 pointer 或 reference 指向一个 local stack 对象,或返回 reference 指向一个 heap-allocated 对象,或返回 pointer 或 reference 指向一个 local static 对象而有可能同时需要多个这样的对象。)
  22. 将成员变量声明为 private(为了封装、一致性、对其读写精确控制等)
  23. 宁以 non-member、non-friend 替换 member 函数(可增加封装性、包裹弹性(packaging flexibility)、机能扩充性)
  24. 若所有参数(包括被this指针所指的那个隐喻参数)皆须要类型转换,请为此采用 non-member 函数
  25. 考虑写一个不抛异常的 swap 函数
  26. 尽可能延后变量定义式的出现时间(可增加程序清晰度并改善程序效率)
  27. 尽量少做转型动作(旧式:(T)expressionT(expression);新式:const_cast<T>(expression)dynamic_cast<T>(expression)reinterpret_cast<T>(expression)static_cast<T>(expression)、;尽量避免转型、注重效率避免 dynamic_casts、尽量设计成无需转型、可把转型封装成函数、宁可用新式转型)
  28. 避免使用 handles(包括 引用、指针、迭代器)指向对象内部(以增加封装性、使 const 成员函数的行为更像 const、降低 “虚吊号码牌”(dangling handles,如悬空指针等)的可能性)
  29. 为 “异常安全” 而努力是值得的(异常安全函数(Exception-safe functions)即使发生异常也不会泄露资源或允许任何数据结构败坏,分为三种可能的保证:基本型、强列型、不抛异常型)
  30. 透彻了解 inlining 的里里外外(inlining 在大多数 C++ 程序中是编译期的行为;inline 函数是否真正 inline,取决于编译器;大部分编译器拒绝太过复杂(如带有循环或递归)的函数 inlining,而所有对 virtual 函数的调用(除非是最平淡无奇的)也都会使 inlining 落空;inline 造成的代码膨胀可能带来效率损失;inline 函数无法随着程序库的升级而升级)
  31. 将文件间的编译依存关系降至最低(如果使用 object references 或 object pointers 可以完成任务,就不要使用 objects;如果能够,尽量以 class 声明式替换 class 定义式;为声明式和定义式提供不同的头文件)
  32. 确定你的 public 继承塑模出 is-a(是一种)关系(适用于 base classes 身上的每一件事情一定适用于 derived classes 身上,因为每一个 derived class 对象也都是一个 base class 对象)
  33. 避免遮掩继承而来的名字(可使用 using 声明式或转交函数(forwarding functions)来让被遮掩的名字再见天日)
  34. 区分接口继承和实现继承(在 public 继承之下,derived classes 总是继承 base class 的接口;pure virtual 函数只具体指定接口继承;非纯 impure virtual 函数具体指定接口继承及缺省实现继承;non-virtual 函数具体指定接口继承以及强制性实现继承)
  35. 考虑 virtual 函数以外的其他选择(如 Template Method 设计模式的 non-virtual interface(NVI)手法,将 virtual 函数替换为 “函数指针成员变量”,以 tr1::function 成员变量替换 virtual 函数,将继承体系内的 virtual 函数替换为另一个继承体系内的 virtual 函数)
  36. 绝不重新定义继承而来的 non-virtual 函数
  37. 绝不重新定义继承而来的缺省参数值,因为缺省参数值是静态绑定(statically bound),而 virtual 函数却是动态绑定(dynamically bound)
  38. 通过复合塑模 has-a(有一个)或 “根据某物实现出”(在应用域(application domain),复合意味 has-a(有一个);在实现域(implementation domain),复合意味着 is-implemented-in-terms-of(根据某物实现出))
  39. 明智而审慎地使用 private 继承(private 继承意味着 is-implemented-in-terms-of(根据某物实现出),尽可能使用复合,当 derived class 需要访问 protected base class 的成员,或需要重新定义继承而来的时候 virtual 函数,或需要 empty base 最优化时,才使用 private 继承)
  40. 明智而审慎地使用多重继承(多继承比单一继承复杂,可能导致新的歧义性,以及对 virtual 继承的需要,但确有正当用途,如 “public 继承某个 interface class” 和 “private 继承某个协助实现的 class”;virtual 继承可解决多继承下菱形继承的二义性问题,但会增加大小、速度、初始化及赋值的复杂度等等成本)
  41. 了解隐式接口和编译期多态(class 和 templates 都支持接口(interfaces)和多态(polymorphism);class 的接口是以签名为中心的显式的(explicit),多态则是通过 virtual 函数发生于运行期;template 的接口是奠基于有效表达式的隐式的(implicit),多态则是通过 template 具现化和函数重载解析(function overloading resolution)发生于编译期)
  42. 了解 typename 的双重意义(声明 template 类型参数是,前缀关键字 class 和 typename 的意义完全相同;请使用关键字 typename 标识嵌套从属类型名称,但不得在基类列(base class lists)或成员初值列(member initialization list)内以它作为 base class 修饰符)
  43. 学习处理模板化基类内的名称(可在 derived class templates 内通过 this-> 指涉 base class templates 内的成员名称,或藉由一个明白写出的 “base class 资格修饰符” 完成)
  44. 将与参数无关的代码抽离 templates(因类型模板参数(non-type template parameters)而造成代码膨胀往往可以通过函数参数或 class 成员变量替换 template 参数来消除;因类型参数(type parameters)而造成的代码膨胀往往可以通过让带有完全相同二进制表述(binary representations)的实现类型(instantiation types)共享实现码)
  45. 运用成员函数模板接受所有兼容类型(请使用成员函数模板(member function templates)生成 “可接受所有兼容类型” 的函数;声明 member templates 用于 “泛化 copy 构造” 或 “泛化 assignment 操作” 时还需要声明正常的 copy 构造函数和 copy assignment 操作符)
  46. 需要类型转换时请为模板定义非成员函数(当我们编写一个 class template,而它所提供之 “与此 template 相关的” 函数支持 “所有参数之隐式类型转换” 时,请将那些函数定义为 “class template 内部的 friend 函数”)
  47. 请使用 traits classes 表现类型信息(traits classes 通过 templates 和 “templates 特化” 使得 “类型相关信息” 在编译期可用,通过重载技术(overloading)实现在编译期对类型执行 if…else 测试)
  48. 认识 template 元编程(模板元编程(TMP,template metaprogramming)可将工作由运行期移往编译期,因此得以实现早期错误侦测和更高的执行效率;TMP 可被用来生成 “给予政策选择组合”(based on combinations of policy choices)的客户定制代码,也可用来避免生成对某些特殊类型并不适合的代码)
  49. 了解 new-handler 的行为(set_new_handler 允许客户指定一个在内存分配无法获得满足时被调用的函数;nothrow new 是一个颇具局限的工具,因为它只适用于内存分配(operator new),后继的构造函数调用还是可能抛出异常)
  50. 了解 new 和 delete 的合理替换时机(为了检测运用错误、收集动态分配内存之使用统计信息、增加分配和归还速度、降低缺省内存管理器带来的空间额外开销、弥补缺省分配器中的非最佳齐位、将相关对象成簇集中、获得非传统的行为)
  51. 编写 new 和 delete 时需固守常规(operator new 应该内涵一个无穷循环,并在其中尝试分配内存,如果它无法满足内存需求,就应该调用 new-handler,它也应该有能力处理 0 bytes 申请,class 专属版本则还应该处理 “比正确大小更大的(错误)申请”;operator delete 应该在收到 null 指针时不做任何事,class 专属版本则还应该处理 “比正确大小更大的(错误)申请”)
  52. 写了 placement new 也要写 placement delete(当你写一个 placement operator new,请确定也写出了对应的 placement operator delete,否则可能会发生隐微而时断时续的内存泄漏;当你声明 placement new 和 placement delete,请确定不要无意识(非故意)地遮掩了它们地正常版本)
  53. 不要轻忽编译器的警告
  54. 让自己熟悉包括 TR1 在内的标准程序库(TR1,C++ Technical Report 1,C++11 标准的草稿文件)
  55. 让自己熟悉 Boost(准标准库)

More Effective c++

  1. 仔细区别 pointers 和 references(当你知道你需要指向某个东西,而且绝不会改变指向其他东西,或是当你实现一个操作符而其语法需求无法由 pointers 达成,你就应该选择 references;任何其他时候,请采用 pointers)
  2. 最好使用 C++ 转型操作符(static_castconst_castdynamic_castreinterpret_cast
  3. 绝不要以多态(polymorphically)方式处理数组(多态(polymorphism)和指针算术不能混用;数组对象几乎总是会涉及指针的算术运算,所以数组和多态不要混用)
  4. 非必要不提供 default constructor(避免对象中的字段被无意义地初始化)
  5. 对定制的 “类型转换函数” 保持警觉(单自变量 constructors 可通过简易法(explicit 关键字)或代理类(proxy classes)来避免编译器误用;隐式类型转换操作符可改为显式的 member function 来避免非预期行为)
  6. 区别 increment/decrement 操作符的前置(prefix)和后置(postfix)形式(前置式累加后取出,返回一个 reference;后置式取出后累加,返回一个 const 对象;处理用户定制类型时,应该尽可能使用前置式 increment;后置式的实现应以其前置式兄弟为基础)
  7. 千万不要重载 &&|| 和 , 操作符(&& 与 || 的重载会用 “函数调用语义” 取代 “骤死式语义”;, 的重载导致不能保证左侧表达式一定比右侧表达式更早被评估)
  8. 了解各种不同意义的 new 和 delete(new operatoroperator newplacement newoperator new[]delete operatoroperator deletedestructoroperator delete[]
  9. 利用 destructors 避免泄漏资源(在 destructors 释放资源可以避免异常时的资源泄漏)
  10. 在 constructors 内阻止资源泄漏(由于 C++ 只会析构已构造完成的对象,因此在构造函数可以使用 try…catch 或者 auto_ptr(以及与之相似的 classes) 处理异常时资源泄露问题)
  11. 禁止异常流出 destructors 之外(原因:一、避免 terminate 函数在 exception 传播过程的栈展开(stack-unwinding)机制种被调用;二、协助确保 destructors 完成其应该完成的所有事情)
  12. 了解 “抛出一个 exception” 与 “传递一个参数” 或 “调用一个虚函数” 之间的差异(第一,exception objects 总是会被复制(by pointer 除外),如果以 by value 方式捕捉甚至被复制两次,而传递给函数参数的对象则不一定得复制;第二,“被抛出成为 exceptions” 的对象,其被允许的类型转换动作比 “被传递到函数去” 的对象少;第三,catch 子句以其 “出现于源代码的顺序” 被编译器检验对比,其中第一个匹配成功者便执行,而调用一个虚函数,被选中执行的是那个 “与对象类型最佳吻合” 的函数)
  13. 以 by reference 方式捕获 exceptions(可避免对象删除问题、exception objects 的切割问题,可保留捕捉标准 exceptions 的能力,可约束 exception object 需要复制的次数)
  14. 明智运用 exception specifications(exception specifications 对 “函数希望抛出什么样的 exceptions” 提供了卓越的说明;也有一些缺点,包括编译器只对它们做局部性检验而很容易不经意地违反,与可能会妨碍更上层的 exception 处理函数处理未预期的 exceptions)
  15. 了解异常处理的成本(粗略估计,如果使用 try 语句块,代码大约整体膨胀 5%-10%,执行速度亦大约下降这个数;因此请将你对 try 语句块和 exception specifications 的使用限制于非用不可的地点,并且在真正异常的情况下才抛出 exceptions)
  16. 谨记 80-20 法则(软件的整体性能几乎总是由其构成要素(代码)的一小部分决定的,可使用程序分析器(program profiler)识别出消耗资源的代码)
  17. 考虑使用 lazy evaluation(缓式评估)(可应用于:Reference Counting(引用计数)来避免非必要的对象复制、区分 operator[] 的读和写动作来做不同的事情、Lazy Fetching(缓式取出)来避免非必要的数据库读取动作、Lazy Expression Evaluation(表达式缓评估)来避免非必要的数值计算动作)
  18. 分期摊还预期的计算成本(当你必须支持某些运算而其结构几乎总是被需要,或其结果常常被多次需要的时候,over-eager evaluation(超急评估)可以改善程序效率)

转自:https://mp.weixin.qq.com/s/GOk0jlbJPl9NNtXmdLz9WQ

男子从殡仪馆打来电话:能不能写写我们的天才儿子

写在前面

阳光很好的一天,金晓宇陪着父亲来报社送照片。目送他们远去的背影,我想到,站在眼前的是一个天才翻译家和他的父亲。

了解他们的故事,你会潸然泪下。这诚然是一个悲伤的故事,但也洋溢着坚韧不拔的爱,无法被摧毁的爱。爱能催生出强大无比的意志,能承受生活沉重的压力。只有父爱才能让一个父亲坚信自己的孩子,不放弃自己的孩子。这个承诺不是一年两年,而是永远、永远。
在命运面前,在不幸面前,一个家庭就像一艘漂泊的小船,劈波斩浪,沉浮与共。我们相信,这艘小船最终能在一个巨大的港湾找到容身之所,会有安定的生活。

以下,是金晓宇父亲金性勇的自述

2021年11月11日上午,我在杭州殡仪馆放好了老伴的骨灰盒,感觉自己手发颤,走路腿也抖。我让几个亲友先走,我还想陪她一会。
老伴脑子清醒时曾跟我说,哪天她走了,骨灰盒先放殡仪馆里,以后是安葬还是洒到江里海里,要等大儿子回家再决定怎么处理。
但我没有打电话给金晓天,现在全世界疫情,他回不来。也没有告诉金晓宇,11月之前他就住院了。
让孩子们以为妈妈还活着吧。
我望着那个盒子,和老伴说:我要打电话了,你同意吧?哪天我也走了,就没有人知道我们儿子的事了。
我从挂在手腕上的小包里,摸出老年手机和一张《杭州日报》。报头上有我抄的“倾听·人生”的电话号码。电话接通了。我说:“你们能不能写我儿子的故事?我儿子是天才,他现在精神病院里,他妈妈今天刚走了。”

男子从殡仪馆打来电话:能不能写写我们的天才儿子

金晓宇和父亲金性勇
6岁那年,玩伴的玩具手枪里射出一根针

我儿子的一只眼睛就此瞎了

我的老家在浙江桐乡,父亲是小学校长,老伴的妈妈,那时候是我的老师。我们两家住在同一个门头里,算得上青梅竹马。
我老伴叫曹美藻。我考进了上海化工学院,美藻考到了南京大学化学系。毕业后,同分配到天津工作。1967年我们结婚了,先是生了大儿子金晓天,1972年又生了小儿子金晓宇。

男子从殡仪馆打来电话:能不能写写我们的天才儿子

金晓宇童年时的家庭合影
1984年,我们带着两个儿子落叶归根回到杭州。这么执意回来是因为心里扎进一根剌,万想不到它变成了一把刀。小宇的命怎么会这么苦?
在天津时,我们住集体宿舍,一间房十五六平米。六岁那年,小宇和邻居孩子一起玩,那孩子手里有一把玩具手枪,可以放小纸球射出来。万没想到那天他放了一根针,一枪打到小宇眼睛里,左眼晶体碎了。
小宇的一只眼睛从此瞎了,只能斜眼看东西。他还反过来安慰我们:没关系,习惯了。
两个儿子都聪明。回杭州后,大儿子考进复旦大学,后来考托福去了澳大利亚。小宇高一时分在尖子班,老师说考大学完全没问题。但有一天,小宇突然和我们说:“我不上大学了,也不要读高中了。”
高中时他突然厌学,情绪大变

家里的电器被他砸了个遍

我们以为小孩子厌学说说玩的,可他真的天天赖在家里。我让朋友帮忙,介绍小宇去解放路新华书店当售货员。我想,过段时间孩子就想回学校了。
两个月不到,书店不要他了。起因是有位老顾客在店里看书,小宇说人家是小偷,争执起来。我又把小宇介绍到排气扇厂当工人,没几天他就不肯上班,说那些工友对他不好。
他不上学后,我和他妈每天上班走之前,他在床上,下班回家,他还在床上。他也不跟我们说话,会突然发脾气,情绪极不稳定,完全变了一个人。

男子从殡仪馆打来电话:能不能写写我们的天才儿子

金晓宇少年时和父亲的合影
有一天,我和他妈妈坐在沙发上看电视,轰隆一声巨响。小宇把厨房的冰箱推倒了。这是他第一次出现暴力行为。
因为这,我们家一直“家徒四壁”。全杭州可能就我家没有电视机,之前被小宇砸坏了三个,往里面灌水。冰箱、洗衣机换过好几个了,还有桌子、书架、柜子、门……好好的,突然轰一声,你说怎么办?
小宇妈妈绝望地问我:“他是疯了吗?”

 

考上了大学,他还是没能留下来

医生说,我儿子是躁狂抑郁症

很长时间,我们不知道孩子这是生病了。当他说想考大学,我们喜出望外,让他进了补习班。小宇高中基本没上过,几个月后,高考成绩让人吃惊,离一本线只差3分。
二本志愿填了杭大外语系,分数也超线了。我们很开心地等学校通知。谁知学校将档案退回,档案里记录了小宇高中时不守纪律、缺课。
七转八转,小宇进了树人大学,可是只读了一年就犯病了。据同学讲,他们几个到外面喝酒,小宇表现得异常兴奋,回校后还往老师的汽车顶上爬,拉都拉不住。
学校以为是发酒疯,把他送到医院。小宇看到我,很愤怒,“你来干什么?把针头拔掉,我要回家!”
我把他带回家。我知道这孩子与学校从此无缘了。

男子从殡仪馆打来电话:能不能写写我们的天才儿子金性勇

有两年,他埋头自学,比上学还用功。两年后,他拿到了浙江大学英语系的自考毕业文凭。
但接着发生了可怕的事,当时我不在家。小宇睡在床上怎么也叫不醒,他妈发现他是吃了安眠药自杀,赶紧和邻居把他送到医院洗胃。幸亏药量不足,孩子救了回来。
又过了段时间,我们听到哗啦一声响,冲进房间看到小宇摔在地上,一圈皮带挂在天花板吊灯和窗户之间。我和他妈抱着他哭,“孩子,你不要做傻事啊!”
我是研究医药化工的,孩子这些表现不是性格问题了,我就看书找原因,小宇的症状符合精神类疾病。去几家医院看了,都诊断是躁狂抑郁症,也叫双相情感障碍,病人会抑郁和躁狂交替发作。小宇不上学,情绪低落,晚上不睡觉,甚至自杀,这些都是在抑郁期;无端猜疑指责别人,狂躁不安,有破坏行为,是转入了躁狂期。

 

不读书不工作不成家都能接受

我们只要儿子活着

精神科专家说这病来得快去得快,危险就在于不知道什么时候来什么时候去,吃药也不能控制,唯一能做的就是及时送医院。1992年起,基本每年都要送小宇进去。
我买了很多精神疾病的书看。最后有两点让一个父亲不至于崩溃:一是通常这类病人一两次自杀未遂后很少再有这个念头,他们会比之前珍惜生命;二是这类病人会在精神领域不同凡响,甚至表现出天才性的创造力。
我读到一本书叫《躁狂抑郁多才俊》,是美国一名精神病医师写的,里面列举了25位历史名人:贝多芬、梵高、牛顿、海明威……他们终其一生都有双相情感障碍的典型表现,承受了超出常人的痛苦。又都是具有伟大想象力的天才艺术家。
懂得这些知识后,我最大的宽慰就是小宇可能不会再自杀了。至于“天才”,我没去想过,毕竟不是所有精神病人都能成为梵高、牛顿,即使成了天才也需要两点:一是活着,二是机遇。
儿子不想死了,我和他妈忽然觉得什么都不重要了,不读书不上大学不工作不成家,我们都能接受——只要他活着。
指责别人,狂躁不安,有破坏行为,是转入了躁狂期。

 

老伴的一场同学会改变了他的命运

“能不能请你儿子在家做翻译”

又过了十年,2010年,老伴去南大开50周年同学会。也许是天怜英才,也许是一个母亲的精诚所至,这场同学会竟然改变了小宇接下来的命运。
听说我家孩子因病没有工作,一位留校做了教授的同学就问她:能不能请你儿子在家做翻译?
我老伴说,小宇的英语日语都很好,请给他一个机会试试吧。

男子从殡仪馆打来电话:能不能写写我们的天才儿子

小宇家的电脑
时光回到上世纪90年代,那是我们家最困难的时期,到处治病要花钱,孩子出门闯祸要赔钱,但我还是竭尽所能满足小宇的要求。他最大的要求就是买书——英语、日语、古文、围棋、音乐、绘画、地理等,各种书籍买了两百多本。
1993年,我冒着被砸坏的风险,花一万两千块钱给小宇买了一台电脑。小宇那天高兴地说:“爸爸,谢谢你!”
之后,他发病时也摔过东西,但从不碰电脑。电脑成了小宇的另一个世界。他也不玩游戏,主要就做两件事:自学外语、看原声电影。他用了六年时间自学了德语、日语,巩固英语。看外语电影,他先看带中文字幕的,看懂后,做一个纸条挡住字幕再看。一部电影反复看N遍,直到完全听懂。
这一切给小宇带来的兴奋和投入,是孩子在躁狂期创造力增强的表现。“机会总是给有准备的人”,我从没想过这句话跟小宇有什么关系。直到十年后,他妈妈开同学会回来,我才忽然觉得,这些年和孩子一起经历的事,就像是一个训练营——
原来,机会真的是给每一个有准备的人。
南大出版社很快寄来了美国女作家安德烈娅·巴雷特的八个短篇小说,让小宇翻一篇试试。

男子从殡仪馆打来电话:能不能写写我们的天才儿子

金晓宇的首部翻译作品《船热》
他以最快速度翻译了其中一篇《船热》。交稿时跟出版社说,如果审核通过,剩下的也请交给我翻。
我很惊讶,这是文学啊,翻译等于再创作,一篇还不知道行不行,一整本书你能翻译好吗?
小宇说,行的,爸爸你放心,我翻的不会比别人差,这些年我出门就是到浙江图书馆,我不是去玩,你到浙图查下借阅登记卡,我借过的每本书,都有金晓宇的名字。
“那你看过几本小说?”
“我看完了图书馆里所有的外语小说。”

 

十年里,他翻译了22本书

老伴同学说:你们养了一个天才!

时间回到2010年,小宇接受了出版社的任务,开始他的翻译人生。十年里,小宇以每年两本书的速度,一共翻译了22本书。他短暂又高产的翻译生涯,是我们全家最难得最幸福的岁月。
2013年,小宇翻译出版了爱尔兰作家约翰·班维尔的英文小说《诱惑者》。原书名《Mefisto》,小宇和编辑讨论时,对方说这个没法意译,用音译吧,就是《梅菲斯特》。但小宇知道,Mefisto是歌德代表作《浮士德》里的角色,这个人物就是一个诱惑者,那么可能诱惑者才是作者的本意。小宇决定采用《诱惑者》作书名,结果出版社非常赞赏,《诱惑者》也成为抢手好书。
翻译日本女作家多和田叶子的小说《狗女婿上门》时,小宇天天看日本相扑比赛,为了提升翻译的准确度。屏幕下方,挡字幕的纸条飞舞。屏幕上,两个只系着腰带的大力士在翻滚打斗。我们父子俩看得哈哈大笑。小宇先后翻译了多和田叶子的五本小说,反响都很好,出版社打算再出合订本。

男子从殡仪馆打来电话:能不能写写我们的天才儿子

再比如《安德烈·塔可夫斯基:电影的元素》,这本书非常难译,小宇专门去看了塔可夫斯基导演的所有电影。南大选派了外国文学专业的顾老师担任本书责编,顾老师又邀请本书作者罗伯特·伯德的博士研究生彭欣为小宇译著撰写了附录。这本书2018年出版,影响很大,网站有电影研究者发文说,“原以为金晓宇译文有错误,特意买了原著对照看,才知道金译没有错,而且比原文还好,文字更细腻……”
孩子一生没有朋友。我作为父亲,最有幸的是在这十年成为孩子最好的朋友、助手。我买了扫描仪、打印机,跑邮政帮他收外文样稿,买资料书,翻译完给他打印样稿,译文每本都是几百页,小山堆一样,再帮他校稿、寄出样书……每本书从样稿到出版,我都是第一读者。惊喜的是我从没看到过一个错字,22本书、近七百万字,你说我不容易?是小宇更不容易啊!
编辑部负责人来我家看过小宇,他说金晓宇译的书稿寄到编辑部,大家都抢着做责任编辑,因为全书没有错字、错句、错译,每本书都好卖,读者反响很好。
南大同学打电话祝贺孩子妈妈,“你们养了一个天才!”

男子从殡仪馆打来电话:能不能写写我们的天才儿子

金晓宇的翻译作品横跨小说、电影、音乐、哲学多个领域
但除了南大,翻译界没人知道金晓宇是谁,社会上没人知道我儿子到底付出了多少心血,更没人知道这些书是一个躁郁症患者翻译的。从没露出过笑脸的小宇,第一次眉开眼笑地告诉我:“爸爸,浙江图书馆里也有我翻译的书,我还特意去查了借书登记本,有很多读者借过金晓宇译的书哦!”
新书出版后,小宇会去查看豆瓣评分,“爸爸,爸爸,都是8分以上,还有很多读者评论好看……”
我一句话也说不出来,只笑着点头,“好、好”。

 

儿子步入正轨,但老伴的身体撑不住了

痴呆这几年,儿子天天照顾她

老伴这一生过得很辛苦,她当年是高材生,有文化有专业,她勤劳节俭,全家人四季衣服都是自己做的。小宇不知砸坏了多少东西,妈妈的缝纫机他从不砸。
2000年前后,老伴开始炒股。我们分工默契,我在家守儿子,她每天去证券交易所。我明白她炒股是为小宇存钱,从孩子童年瞎了一只眼后,她的心就扑在小宇身上。后来小宇的病让我们毫无办法,她的绝望无奈都埋在心里了。小宇在家翻译,让她看到一丝光亮,但她自己这盏灯却要灭了。
2015年,老伴说自己记性不好,不炒股了,要把存款都交待给我。我这才知道她有200万元的理财产品拿不回来,我想尽办法追回款子,还是有50万元丢了。这件事后老伴的健康每况愈下,之后确诊得了阿尔茨海默症,接着日常生活不能自理,在床上躺了三年。
小宇非常难过,他说我能翻译书是妈妈的功劳。每次出版社寄十本样书给小宇,他都第一时间冲到床边送到妈妈手里,讲给妈妈听。后来,他妈妈开始不会说话、不认得家人。

男子从殡仪馆打来电话:能不能写写我们的天才儿子

金晓宇少年时的家庭合影
古话说,久病床前无孝子,但我儿子就是真孝子。妈妈痴呆了好几年,他从没对妈妈发过脾气,还为妈妈做了很多事。白天他照顾妈妈,负责买菜,每天买妈妈喜欢吃的虾,饭后洗碗,再给老妈洗脸。我管晚上的事,做三餐饭,给老伴剥虾喂饭。
他妈妈三年没上过厕所,每两小时要接一次大小便。先前她的脚还有力气,抱她坐到床边一个便桶椅上,后来只能抱着拖拽下来。我80岁了,真抱不动,幸亏有小宇。没有小宇,我们可能都死了。
小宇很仔细很耐心,有时小宇做这些事时,他妈妈的眼里有泪。每天小宇抱着妈妈喊“老妈啊,老妈啊”。他心里记着妈妈的恩,从六岁剩下一只眼,妈妈就为他流泪,抱着他不知哭了多少次。我心里想说,儿子啊,你长大后更是不知妈妈为你哭过多少次啊。

男子从殡仪馆打来电话:能不能写写我们的天才儿子

这三年,我真正明白了什么叫相依为命,这三年也是小宇翻译冲刺时期,除了南大,别的出版社也找他翻译了,书一本比一本厚。孩子的病症也奇迹般减少,照顾妈妈,日夜翻书,小宇一直很安静很努力,直到去年11月。
小宇的第22本是德文书。早在2016年,他就接到出版社约稿,请他翻译德国思想家本雅明的《书信集》。这本书有53万字。拿到德文书稿后,小宇通宵达旦查阅资料,连发病都忘了,只用一年时间就交出译稿。
可惜,因为出版社的原因,这本书迟迟没能出版。小宇天天在等。
这些年我们非常感谢社区、感谢湖墅派出所、拱墅区残联、侨联的照顾,让我儿子能够健康地走向社会、为社会做更多贡献。
这些年也有人不理解,说我要儿子搞翻译是为了挣钱,我只有苦笑。他们不知道翻译根本不挣钱,新书只是我儿子命悬一线时的强心剂。

 

儿子不带手机一个人去了温州

他回家后若无其事,我却心里一紧

书久等不见,我最担心的事还是发生了,去年11月之前小宇跑到温州去了。
每年11月到第二年3月,是小宇最难熬的日子。去年10月,儿子已经很久没出门。这天吃过晚饭六点钟,他说:“爸,晚上药我吃过了,不会走远,7点肯定回来。”我叮嘱他早点回家,别的不敢多问。
小宇出门从来不带手机,7点、8点、9点……11点,我急了,跑到派出所报案。
过去他在马路上瞎晃,民警碰到都会带他回来。第二天,民警查监控,发现小宇晚上乘151路到了城站火车站,买了去温州的票。他身上可能有一百多块钱。
我急得团团转,小宇却回家了。问他去温州干什么,他说下车吃了点东西就回来了。看他若无其事,我心里叫苦,这是躁狂症发病的前兆啊。
又过了几天,小宇过马路,迎面一个快递员,他一拳打掉了人家的门牙……不久,七院来人,将小宇带走。儿子呼天喊地:爸爸救救我,我不去医院啊,不要去啊。
一个晚上,老伴走了

我什么都不能为她做了

11月8日晚上,我像平常一样睡前摸老伴的额头、脸,再去摸脚。怕她冷了、热了,摸了才知道。
这天,我摸哪里都是寒的,脚像冰块一样。我赶紧开空调,打到25度,又抱了一床毯子加在被子上。过半小时再摸,还是没有一丝热气。
我慌了,抱着她的头靠在怀里,“靠牢我靠牢我”,我脸贴着脸,但还是越来越冷。“你不能走,不能走啊!”,我把脸贴得更近,手哆嗦着摸她的鼻子,没气了,往下摸,心脏不跳了。
我不知道怎么办,完全没有思想准备。她走了,我儿子没有妈妈了。

男子从殡仪馆打来电话:能不能写写我们的天才儿子

我还在计划给老伴做插管手术,有个90多岁的邻居也是这个情况,做了手术还活着。我为什么没早点给她做呢?这一夜我守着老伴越来越冷的身体,流泪,自责,后悔。
虽然她早就不认识我,早就什么都不知道,但我知道她还活着,知道我每天是为她、为儿子活着。她走了,我没有一丝一毫的解脱。我已经习惯她活着,习惯天天为她做事。三年来我睡她床横头的沙发,晚上我能听见她的呼噜声、呼吸声、咳嗽声……我像钟表一样准时,两小时准会醒来,跟她说话,给她翻身,喂她喝水……现在这么安静,什么都听不到了,什么都不能做了。
上周我去医院看过小宇,给他送点吃的。每次去那里看他,每次都听他哭叫,“求求你带我回家,爸爸我们回家吧……”
儿子春天会回来,他会让妈妈看他的新书。
《本雅明书信集》终于寄来了。
 
最新消息
金晓宇85岁父亲金性勇老人告诉记者:小宇已经出院回家,等待已久的《本雅明书信集》样书也已收到,预计下月上市。目前他正在全力翻译第二本本雅明的著作《拱廊计划》。老人感谢了大家的关心,但也婉拒了所有物质帮助。
 
来源:杭州日报

监制:张越

编辑:周喆、李昂、王宜玄、王朝

实习:孙誉宁、满兴莲、马如玥

转自:https://mp.weixin.qq.com/s/tdyrzM71OVDuFvlb52gd0A

 

我卧底了一家中介门店,背后看到…

之前一个周末,我跟一个中介朋友约饭,他迟到了
他说周末比较忙,忙着“练”房东呢…
 
没想到这年头还能听到这个词
现在都怎么“练”呢,他说先跟房东说今天会有客户来看房,看好了就能订,然后雇假客户去看房,最后约房东到门店谈价格
我卧底了一家中介门店,背后看到…
当然不是真谈价格,而是要看看房东的心里价位,顺便压压价格,促成交,这就是摸底、排雷和试六大项,对外叫面谈,内部代号“MT”
类似这样的代号还不少,用起来方便,被房东看到也没事,谁能看懂
我卧底了一家中介门店,背后看到…
是不是还挺小心机的,中介朋友考我说:跟进,EK,以ZY名义消极房东,这句什么意思
 
没想到一个门店背后还有那么多套路,为了获得更多内幕,我准备去卧室一家中介门店,去看看背后到底是怎么运作的
没想到,真的进入之后发现足够的魔幻
 
记录了一些工作笔记,大概有这一些……
01
“布点、跟踪、穿插、游击”
如果非说小心机的话,他首推找客户这件事
简单说就是:布点、跟踪、穿插、游击
每个门店都会有自己深耕的小区,每天早9点到晚上7点半,小区门口永远有附近中介门店的一个人在门口发传单
每周末会在小区正门、后门、所有进出口上布点,只要有一个中介来带看,他都了如指掌
如果有别家中介带着客户从一个小区到另一个小区,群里也会奔走相告,看看隔壁小区有没有人,没人的话,派人去支援
支援过去做的都是一件事,跟踪
看你进小区左拐还是右拐,都知道你去看的是哪套房,小区里在卖的房他们几乎门儿清
我卧底了一家中介门店,背后看到…
进小区右转了,那就一定是8号楼1单元501,于是就派小哥穿插到别家中介前面等着他们,或者直接到楼里面等,这叫穿插
一般来讲,别家中介和客户进了这栋楼,穿插中介都不会让你发现,大概你们进去4、5秒他才会刷卡进去,然后在7楼、8楼的楼梯拐角处那里猫着听动静
穿插不是为了当面截胡,而是伺机而动
中介和客户总有分开的时候,只要你跟的不紧,那我就中场截胡,如果到小区门口才分开,我就到小区门口等你们分开后,再上去问一句
“姐,我看您刚看的两房,我这有一套同小区的,要不要看看”
就算客户去地铁,我跟进地铁行不行,如果开车更好办,就会有泊车电话,前面步骤全部省略,直接电话问要不要看更多一套房源
泊车电话要不到,去黑车产业链查车牌,25块/个,这钱就买一个号码不便宜,但是架不住客户够精准
一般来说,开车一来就是一家人,这样现场就能做决定,如果一辆车带着老人、孩子,开着一个车,这个车还是30万以上
这种情况就说明有购买力,决策人在场,这时候什么20、25,早就不在乎这点钱了,话术都想好了
“您好,我这有一套房,也是这个小区的,是我们独家的,您还没看过,来都来了,要不要看下”
这个时候没人会拒绝,来都来了,干嘛不多一个选择,如果看中了,这就是“一枪头”
我朋友说了句励志又好笑的话,“只要有心,都是办法”
02
为了独家房源,他们可以有多拼
可以看的出来,不管是布点还是游击,前提都得是我有房源
对中介来说,只要有房,就不愁没客户,有时候一家中介公司80%成交都是来自独家房源,所以挖房源很重要,尤其是独家
一般一个门店在一个小区有2-3套独家,中介基本可以横着走,其他中介这时候往里面带看,几乎就是给独家房源的中介送客户
所以有些小中介门店挨着客户多的中介门店开也有好处,只要有独家房源,就不愁开单
我听中介朋友说过,他为了深耕一个小区的独家房源,甚至自己搬到这个小区去住
为了争取房东的好感,他们也会自己维护小区做社区服务,服务的主要内容差不多就是捡垃圾
而且一定是趁大家早上上班的时候,这时候大家正出门可以看到,白天都不在家,晚上下班时间点也不固定
不要小看这一点,做足时间差不多在半小时、一小时左右,你的业主会看到你,看着中介身上的衣服,无意中加深了一遍品牌,而且也会多点好感
足够让业主在挂牌或者卖房的时候,多想到一点点就赢了
如果得到消息说小区哪家房子挂出来的时候,小哥们就开始出动了
首先,亮家伙,我们有多少门店、多少业务员、多少刷新服务、每天被推荐多少次…
其次,软磨硬泡,每天维护、定时拜访、反复推销
还有这种烧脑的局中局
我卧底了一家中介门店,背后看到…
明明自己是s价的那个,还托底交流,大概率可以赢得信任,拿到独家
不得不再感叹下,没想到现在中介都已经把活做的这么细了
03
“记住,无状况不成交”
中介朋友说,他带客户去看房,基本都会安排状况
到楼下会遇到第一个状况
我卧底了一家中介门店,背后看到…
其实这时候根本没客户
往里进,电梯下来了,一个中介带着老太太
我卧底了一家中介门店,背后看到…
老奶奶是雇的
到门口了,被堵门了
我卧底了一家中介门店,背后看到…
当然了,还是没客户
到这还不是全剧最高潮,等你到房子里面正在看房的时候,这时候会有人冲出来,气势汹汹的对你的中介说
我卧底了一家中介门店,背后看到…
一通下来,一个真客户都没有,就你自己
是不是觉得这是很久之前才会发生的事,其实就算是现在,这种情况依然有
这些“小剧场”,就是一个个“状况”,对中介来说,无状况不成交
而且如果中介不这么做,尤其复看的时候无状况,回到门店就会被批一顿
如果在你看完一套房,犹豫墨迹不能决定的时候,不走又不定,这时候业务员就会给店长打电话,或者直接在群里扣数字
扣1后,店长电话就来了 
我卧底了一家中介门店,背后看到…
如果赶上周末,还得扣2
我卧底了一家中介门店,背后看到…
这时候可能全店的人都屋里待着呢,想要的效果就是现在市场太好了,如果市场不好,那是别的区的事,我们这不存在
扣3,功能更高级,那边就不再是经纪人,可能是房东
我卧底了一家中介门店,背后看到…
话说到这就两个结果,同意加就加5w,不能加,那就给你推荐一套一样好的,再不买就没那么走运了
最后整体效果就是,这个市场很好,你最好赶紧买
04
中介为什么这么拼
为什么那么想抢独家、抢客户、促成交
我问我那位中介朋友,干嘛这么拼,安安静静做一个中介不好么
他说我也不想,上传信息、带看、客户维护、驻守,这些都是量化考核,没达标就罚钱,还有体罚
一般的指标没有达成的话,男生就罚30-50个俯卧撑,女生就是30-50个深蹲
罚的比较严重的就是长跑或者爬楼,20多层楼,两上两下,有的区域楼层比较高的30多层就运气不太好了
不过运气最差的是,区域楼层都低,那就只能去爬区域商业写字楼,层高4m,普通居民楼的1倍多
平时忙也没关系,可以下班后罚,跑完打卡下班
每周开店长会的时候,没有找到独家房源就要“仰望”,就是在别家店长做分享的时候,在旁边迈开弓子布微微抬头仰望对方
十几二十个店长分享起来,一通分享下来至少50分钟,如果后面第二周还没有,就举灭火器仰望
这样一套奖罚激励制度下来,团队只能拼了,手段也出来了,小心机也出来了
不光二手房,新房也是,不过故事都发生在积分摇号前
前台、岛台、沙盘、洽谈区一套完整的流程走下来,最灵魂设置,是岛台,这里一定会安排一个靠谱的人在那坐着
如果洽谈区有一桌快要成功了,销售就会提示岛台“喊一个”,喊一个假控、或者喊一个砸蛋
 
然后,跟你说几个已经卖掉的,或者说确实不让你买的,想要的效果不是要你买,而是让你抢
 
为什么我们要这么拼…
05
其实现在市面上的中介,基本分两种
一种就是拼平台资源的,这种中介不愁客源流量、也不愁房东挂牌
还有一种就是拼人效的,流量和资源倚靠的对象更多是个人,或者说一个团队机制、一套价值体系
有时候我经常在想,未来我们更需要的是哪一种
 
以上为正文,来自巧克丽丽
 

 

转自 : https://mp.weixin.qq.com/s/bpFdGCaCzkMq8VT90A9UUg