文章目录
- 1、前景提要
- 2、场景还原
- 3、问题根源
- 4、修复方案
- 标题方案1:将父类成员改为 protected
- 方案2:在父类中提供 get 方法
- 总结
1、前景提要
最近在写一个自定义异常类的代码时,我遇到了一个经典的C++继承问题。当时我觉得既然子类继承了父类,就应该像访问自己的私有成员一样,直接访问父类的private成员,结果编译器直接报错了。今天就来复盘一下这个踩坑过程,顺便把C++继承的访问权限规则彻底理清楚。
提示:以下是本篇文章正文内容,下面案例可供参考
2、场景还原
- 我写了一个父类Exception,它包含两个private成员:_errmsg(错误信息)和_id(错误码)。
- 然后我又写了一个子类SqlException继承用它,用来处理SQL相关的异常。
- 在子类的what成员函数中,我想把父类的_errmsg拼接到自己的错误信息里,于是写了这样的代码:
classException//基类{public:Exception(conststring&errmsg,intid):_errmsg(errmsg),_id(id){}private:string _errmsg;int_id;};//classSqlException:publicException{public:SqlException(conststring&errmsg,intid,conststring&sql):Exception(errmsg,id),_sql(sql){}virtualstringwhat()const{string str="SqlException";str+=_errmsg;str+="->";str+=_sql;returnstr;}private:conststring _sql;};结果编译器直接给我报了一个错
'_errmsg'is aprivatemember of Exception我当时就懵了:我不是已经继承了父类了吗,为什么不能直接使用它的私有成员?
3、问题根源
后来我才明白,C++的继承并不是把父类的所有成员都“复制”给子类,而是有严格的访问权限控制:
父类成员权限 子类继承后访问权限(public继承)
| 父类成员权限 | 子类继承后访问权限(public继承 |
|---|---|
| public | 保持public,外部和子类都能访问 |
| protected | 保持protected ,只有子类能访问 |
| private | 子类完全无法直接访问,只能通过父类的 public / protected 接口间接访问 |
简单来说,父类的 private 成员是父类的“私有财产”,即使是它的子类也无权直接触碰。
这个设计是为了保证封装性,让父类可以自由修改自己的内部实现,而不影响子类。
4、修复方案
想通了原理之后,我就找到了两种可行的修复方法:
标题方案1:将父类成员改为 protected
这是最简单直接的方式,把父类的 _errmsg 和 _id 从 private 改成 protected,这样子类就可以直接访问了
classException//基类{public:Exception(conststring&errmsg,intid):_errmsg(errmsg),_id(id){}protected://privatestring _errmsg;int_id;};方案2:在父类中提供 get 方法
如果不想破坏父类的封装性,可以在父类里提供 public 的访问接口,让子类通过这些方法间接获取私有成员:
classException{private:string _errmsg;int_id;public:stringgetErrMsg()const{return_errmsg;}intgetId()const{return_id;}// ...};然后在子类这样调用
virtualstringwhat()const{return"SqlException: "+getErrMsg();}总结
这次踩坑让我深刻理解了:继承不等于拥有父类的私有成员。
C++的访问权限规则不是为了故意刁难开发者,而是为了让代码更健壮、更易于维护。
遵守这些规则,能让我们写出更符合面向对象设计思想的代码。
如果你也遇到了类似的问题,希望这篇文章能帮你少走弯路。