加入收藏 | 设为首页 | 会员中心 | 我要投稿 源码网 (https://www.900php.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 创业 > 经验 > 正文

关于C++面向对象设计的访问性问题详解

发布时间:2020-12-25 00:31:38 所属栏目:经验 来源:网络整理
导读:副标题#e# 前言 最近在看Scott Meyers大神的《Effective C++》和《More Effective C++》,虽然这两本书都是古董级的教参了(当然针对C++11/C++14作者所更新的《Modern Effective C++》英文已经发售了,不过还没中文翻译版本),但是现在看来仍然收益匪浅,而

因为上面说到我们不应该重新定义一个继承而来的non-virtual函数,所以到这里我们可以说:绝对不要重新定义一个继承而来带缺省参数值的virtual函数的参数默认值。其原因是:virtual函数是动态绑定的,而缺省参数是静态绑定的。

所以如果基类和派生类的参数默认值不一致,则使用引用、指针调用发生参数默认值静态绑定和调用函数体动态绑定将会非常的诡异,所以需要避免这种情况。还有就是如果虚函数参数再基类指定的参数缺省值,而派生类override的时候没有指明参数缺省值,此时如果客户端以派生类对象方式调用该函数,则发生的是静态绑定,需要显示指定参数值;而如果客户端以指针、引用的新式调用该函数,则发生的是动态绑定,可以不指定其带有缺省值的参数。

class Shape {
public: virtual void draw(ShapeColor color = Red) const = 0; ...
};
class Circle: public Shape {
// 如果以对象模式调用draw,必须指定color参数而不能使用缺省参数
public: virtual void draw(ShapeColor color) const; ... 
};

解决这个问题的一个方式是使用NVI手法,其public non-virtual接口提供默认默认值(且不会被派生类重写),而private virtual不使用默认默认的特性以规避这种可能的不一致性。

3.4 private继承

private继承没有”is-a”的契约关系了,在使用上一个巨大的差异是:编译器不再会自动将一个派生类对象转换为一个基类对象了,这意味着原本接收基类对象的函数参数将不再能够为其传递派生类对象作为实参了(对象、引用、指针类型都不允许,编译器会报基类S是派生类T不可访问的基类);同时由基类继承而来的所有成员,在派生类中都会变成private的访问权限。

private继承意味着只有实现部分被继承,接口部分被全部略去了,所以private继承应当是采用基类的某些功能帮助派生类完善其功能,从某种情况下说具有”has-a”的符合类型,所以除了考虑到派生类需要访问基类protected成员和virtual的因素被牵扯进来,否则应该尽量使用组合类型来代替private继承,而且即使如此,也可以使用下面的手法瞒天过海:

class Timer { 
public: virtual void onTick() const; ... 
};
class Widget {
private:
 class WidgetTimer: public Timer {
 public: virtual void OnTick() const; ...
 };
 WidgetTimer timer;
};

关于protected继承,连Meyers大神都没用过,那么我又何必废脑经去考虑他……

参考

Effective C++

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对编程小技巧的支持。

(编辑:源码网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读