尽管很多知名译本都把C++面向对象里有继承关系的类称作基类和派生类,但人们很多口语化的表达里还是叫他们父类和子类,毕竟…你继承了我嘛,非亲非故的,谁让你继承。
恰逢今天父亲节,我们就来聊聊C++里对父亲和儿子这一关系的设计。读程序,品人生。
什么东西你不能给儿子分享,却可以跟朋友一诉衷肠?
当然是父辈间的一些隐私啦。
1
回想起我学C++面向对象的时候,正好是《琅琊榜》风靡全国之际。可惜我那会儿沉迷美剧《权力的游戏》,整体张口闭口兰尼斯特有债必偿,分析维斯特洛第一搅屎棍的阴险计谋,震惊血色婚礼的血腥绝望,感叹剧组服化道的极致奢华,对这部国产剧并不感冒。
可我家那位是胡歌的铁粉,已经看了琅琊榜不下二十遍,而且每次看苏哥哥都是花痴脸星星眼。终于在她刷第二十一次的时候,我也陪她看了一遍。
剧里描述了两代人的恩怨故事,父辈代表有皇帝梁王,将军林燮,侯爷言阙、谢玉,特务科首领夏江,江湖势力卓鼎风。儿辈代表有梅长苏,靖王,誉王,萧景睿,言豫津。
父辈之间有很多故事,很多秘密。而这些秘密,隐私他们会跟朋友分享,跟朋友合谋,跟朋友商量。都是他们那一代人的风流韵事,前尘过往,没必要让小辈知道。
所以谢玉跟夏江联手杀了林燮,跟卓鼎风密谋刺杀梅长苏,言侯爷跟道士设计炸死皇帝,都是他们父辈之间
private
的秘密,绝对不会让儿子知道。
多少人身陷险境,都是因为知道的太多了。不让你知道,不让你访问,本质上,也是一种
protected
。
所以小时候你无数次被人怼说“大人的事小孩别插嘴,不该问的别问”时,就是因为你企图去访问父类的private成员,被系统报错警告了一次。
C++里对于父类子类友元类访问控制的设计,跟上文所述异曲同工,不可谓不精妙。
2
一个类里的成员属性可分为
public、private、protected
。
public顾名思义为公开,是一些可以暴露给外界的东西。譬如你的名字,毕业院校,工作经验,专业方向,你的履历等等这些是可以公开的告诉公司的,别人通过你本人访问你的这些属性也理所应当。
但同样,有public就有private。你三岁尿床,八岁拉裤子,十五岁翻墙去网吧,上周还去医院看过肛肠科这些隐私我觉得没必要公开吧……别人若想通过你本人访问这些隐私,建议直接一个白眼翻回去。
不过,你本人虽然不允许别人访问private隐私,但别人可以通过谁知道你的隐私呢?当然是你的那些管不住嘴的狐朋狗友们,是不是很符合逻辑。
人生在世,每个人都是孤独的个体,都需要朋友来分享喜怒哀乐,商量生活琐事。谁还没几个从穿开裆裤一起玩到大的好朋友,谁还没一些可以互诉衷肠的知己红颜。
所谓你是我最坚硬的盔甲,同时也是我最柔软的
软肋
:
我公开的东西,
大家都
可以访问;我保护的东西,
我,我儿子和我的朋友
可以访问,我的隐私,只有
我和我的朋友
可以访问。
简单来讲,我的一切,我的朋友都可以访问。
嗯,设计这个特性的人,一定对朋友很好,重情重义。
同样,在C++里,一个类的所有成员,该类的友元类friend class都可以访问。而private成员,只有友元类可以访问使用。
不过朋友这个事呢,是单向的。你拿人家当朋友,人家不一定拿你当朋友。萧景睿把梅长苏当朋友,把自己的后背完全交给了他,但梅长苏的秘密景睿却一无所知。
所以C++类里,friend class也是
单向
的,我可以访问你的隐私,不代表你可以访问我的。除非我也声明你是我的friend。很合理吧。
fiend class也
不具备传递性
,即我跟你是朋友,但我的另一个朋友却不一定跟你是朋友,除非你也声明他是你的friend。很合理吧。
所以你在设计类的时候,如果有些属性你不希望暴露给所有人,但又不得不让某些指定的模块使用,那就把这些成员划分到
private
属性里,同时把需要访问这些成员的模块声明为该类的
友元类或友元函数
。
举一个实际代码的例子:
class Base{
public:
int GetMyName();
protected:
double GetMyMoney();
private:
std::string GetMySecret();
friend class MyFriend;
};
class MyFriend{
public:
std::string TalkToEveryone(){
Base base;
return base.GetMySecret();
}
};
3
那么父亲虽然对朋友那么好,那么开诚布公,却还是不如对自己儿子亲。毕竟骨肉相连,血浓于水嘛。
朋友只能访问,儿子可以继承啊!所有public属性的东西,自然毫无意外的会留给儿子。
但刚才我也频繁提到了保护
protected
这个词,就是想加深你的印象。父亲对儿子,天然是有保护欲的。以及父亲会让自己继承自己的财产,财产也是受保护的吧。
所以父类和子类之间,牢记
保护
二字,牢记
protected
这个词。所有protected属性的成员,都是留给儿子的。而外人可用不到。
所以在设计类的时候,如果有些属性你不希望暴露给所有人,但你希望给子类留着,那就把这些成员都划分到protected属性里。
一个实际代码的例子:
class Base{
public:
int GetMyName();
protected:
double GetMyMoney();
private:
std::string GetMySecret();
};
class MySon:public Base{
public:
void SpendMoney(){
double money = GetMyMoney();
findGirls(money);
}
};
不过继承也是分级别的,C++里对类的继承分为public继承,protected继承,private继承三种,三者的访问权限也是由低到高的。
在按照某种权限方式继承时,会将权限低于自己的成员提升至跟自己同一级别,而无法将权限高于自己的成员拉低。
篇幅所限,虚函数,虚继承,虚表和虚指针这些,我们下次再详细聊聊。