您的位置:首页 > 编程语言 > C语言/C++

20180321 C++ 避免遮掩继承而来的名称

2018-03-23 10:08 387 查看
20180321 C++ 避免遮掩继承而来的名称

C++的名称遮掩规则(name-hiding relue)所做的唯一事情就是:遮掩名称。至于名称是否是相同或不同的类型,并不重要,如double类型的局部变量x遮掩了int类型的全局变量x。

现在考虑继承关系:

eg:
class Base{
private:
  int x;
public :
  virtual void mf1() = 0;
  virtual void mf1(int);//重载mf1
  virtual void mf2();
  void mf3();
  void mf3(double);//重载mf3
  ...
}
class Derived:public Base{
public:
  virtual void mf1();
  void mf3();
  void mf4();
  ...
}
上述代码中,基类中的所有名为mf1和mf3的函数都被派生类的mf1和mf3函数遮掩掉了。从名称查找观点来看,Base::mf1和Base::mf3不再被派生类继承!

Derived d;
int x;
...
d.mf1();//没问题,调用Derived::mf1
d.mf1(x);//错误,因为Derived::mf1已经遮掩了Bsase:mf1
d.mf2();//没问题,调用Base::mf2
d.mf3();//没问题,调用Derived::mf3
d.mf3(x);//错误,因为Derived::mf3已经遮掩了Bsase:mf3

你可以使用using声明式达成目标:

eg:
class Base{
private:
  int x;
public :
  virtual void mf1() = 0;
  virtual void mf1(int);//重载mf1
  virtual void mf2();
  void mf3();
  void mf3(double);//重载mf3
  ...
}
class Derived:public Base{
public:
  
  using Base::mf1;
  using Base::mf3;
  //让基类中的名为mf1和mf3的所有东西
  //在派生类的作用域中都可见(并且public)

  virtual void mf1();
  void mf3();
  void mf4();
  ...
}

下面进行如下操作:
Derived d;
int x;
...
d.mf1();//仍然没问题,调用Derived::mf1
d.mf1(x);//现在没问题了,调用Derived::mf1
d.mf2();//仍然没问题,仍然调用Base::mf2
d.mf3();//没问题,调用Derived::mf3
d.mf3(x);//现在没问题了,调用Base:mf3

这意味着,若你继承父类并加上重载函数,而你又希望重新定义或覆写其中一部分,那么你必须为那些原本会被遮掩的每个名称引入一个using声明式,否则某些你希望继承的名称会被遮掩。

有时候当不想继承父类的所有函数时,是可以使用一个简单的转换函数(forwarding function),eg:
class Base{
public:
  virtual void mf1() = 0;
  virtual void mf1(int);
  ...          //与前同
};
...
Derived d;
int x;
d.mf1();//很好,调用的是Derived::mf1
d.mf1();//错误! Base::mf1()被遮掩了

inline转换函数(forwarding function)的另一个用途是为那些不支持using声明式(注:这并非正常行为)的老旧编译器另辟一条新路,将继承而得的名称汇入派生类作用域中。

注意:
1、派生类里的名称会遮掩基类里的名称。在共有继承下从来没有人希望入如此。
2、为了让被遮掩的名称重见天日,可使用using生命式或转换函数(forwarding functions)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: