而来的名称"/>
c++ 避免遮掩继承而来的名称
参考 effective c++ 条款33
我觉得看完书中的 总结一下
感觉就是在讲作用域的规则,在继承中作用域的规则
编译器查找同名变量函数的规则
double num = 5; //global 变量int main()
{int num = 3; //local 变量cout << num << endl;
}
运行结果大家都知道是 3
编译器在局部函数 main 内 首先寻找 名字为 num 的变量
如果找不到 就去外层作用域继续找 还找不到就找有没有 global
c++ 名称遮掩规则 所做的唯一事件就是遮掩名称
这个名称变量的类型是否相同并不重要 上面就是 int num 遮掩了 double num
上面比较直观简单 向下递增难度讲讲
继承中的遮掩名称
看一下这个继承结构
基类 实现了3个 函数
- 纯虚函数 mf1()
- 虚函数 mf2()
- 普通函数mf3()
派生类 重新实现了 纯虚函数 mf1()
实现了自己的函数 mf4()
mf4() 中 又调用了 mf2()
当编译器执行到 mf4 中时 看到 mf2 要知道他是啥东西
- 先在 local 函数 mf4() 作用域内找有没有 mf2()
- 在去Derived 中 找有没有 mf2()
- 在去Derived 的父类中 继续找有没有 mf2()
- . . . . . .
- 继续向外层找 找不到就报错了 说没有 mf2()
继续增加难度 继承中出现重载
仔细看上面的规则
int x = 1;Derived d;d.mf1();d.mf1(x);d.mf2();d.mf3();d.mf3(x);
这段代码执行会发生什么呢?
报错了 说明 d.mf1(int) 和 d.mf3(double) 继承失败了
什么原因呢?
编译器 不管你的函数是不是虚函数 是不是重载
因为编译器在查找名字时,并没有“为重载而走的很远”,C++的确是支持重载的,编译器在发现函数重载时,会去寻找相同函数名中最为匹配的一个函数(从形参个数,形参类型两个方面考虑,与返回值没有关系),如果大家的匹配程度都差不多,那么编译器会报歧义的错。
首先找 作用域内 mf1() 和 mf3 有没有同名的 如果有 那么就不会去上层找了
也就是说 重载的带参的 base mf1(int) 和 mf3(double) 被 derived class 内的 mf1() 和 mf3() 给 遮掩掉了
我现在就要调用父类重载的函数 现在有两种办法解决这个问题
1.采用 using 声明
用了using,实际上是告诉编译器,把父类的那个函数也纳入第一批查找范围里面,这样就能发现匹配得更好的重载函数了。
这样就不报错了 当查找 mf1 时 编译器发现两个就会按照重载函数的规则执行。
2.采用 inline 转交函数
也重载一个 带 int 的 mf1(int x) 函数
然后内部实现时 调用基类的 函数 就完成了 我们想要的的效果了
注意:
1.派生类的名称会遮掩基类的名称,在public继承下从来没有人希望如此
2.可以用 using 声明 或者 转交函数 解决这个问题
更多推荐
c++ 避免遮掩继承而来的名称
发布评论