Effective C++ 条款33 避免遮掩继承而来的名称

1. C++基类和派生类的作用域为嵌套关系,同时存在作用域屏蔽规则,例如:

复制代码
class Base{
public:
    void fun();
    ...
private:
    int a;
    ...
}
class Derived:public Base{
    ...
}
复制代码

那么Derived和Base之间的作用域关系就像这样

如果Derived中没有定义a和fun,那么对在Derived作用域内对a的fun的使用将会由内而外直至全局作用域逐层查找;

如果Derived中定义了a和fun,那么会使用Derived中的a和fun,但是如果Derived中a和fun的定义如果像这样:

复制代码
class Derived:public Base{
public:
    void fun(int);
    string a;
    ...
private:
    ...
}
View Code
复制代码

此时如果在Derived内存在如下语句:

a=1;
fun();

都会编译不通过,因为由于名字屏蔽,Base的a和fun在Derived中将不可见,这就是作用域屏蔽规则.因此派生类对基类函数的重写将不是overload(重载),而是“隐藏”

2. 在采用public继承时,如果派生类重写基类函数,名字屏蔽会使得基类中同名函数在派生类中不可见,这实际上违反了条款32"public继承中派生类要完全继承基类接口"的原则,如果使基类的同名函数在派生类中仍然可见,可以使用using声明式:

复制代码
class Derived:public Base{
public:
    using Base::fun;
    void fun(int);
    ...
private:
    string a;
    ...
}
View Code
复制代码

如果并不想继承Base类所有的fun函数(private继承中可能出现),则可以使用"转交函数"(forwarding function)的方法,如下:

复制代码
class Derived:private Base{
public:
    void fun(){
        Base::fun();
    }
    void fun(int);
    ...
private:
    string a;
    ...
}
View Code
复制代码

 

posted @   Reasno  阅读(231)  评论(2编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示