打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
试题:两个基类有同名的虚函数要实现, 怎么办?
分类: c++ 笔记 试题 2012-01-06 11:35 440人阅读 评论(2) 收藏 举报
先把问题陈述一下:

有两个类A, B, 它们可能是别人实现的(或是别人提供的库中的类), 很复杂且已经在用, 你不能修改他们, 你想写一个类C同时具有这两个类的特性, 因为自己实现它代价实在是太大, 所以你想到用C继承A, B以达到效果, 但是有一个问题, A, B具有一个同名的虚函数, 你在C中怎么重新实现这个虚函数呢? 先看下面的代码:

  1. #include <string>  
  2. #include <iostream>  
  3. using namespace std;  
  4.   
  5. class ChineseName  
  6. {  
  7. public:  
  8.     virtual string getname()  
  9.     {  
  10.         return string();  
  11.     }  
  12. };  
  13.   
  14. class EnglishName  
  15. {  
  16. public:  
  17.     virtual string getname()  
  18.     {  
  19.         return string();  
  20.     }  
  21. };  
  22.   
  23. class Name : public ChineseName, public EnglishName  
  24. {  
  25. public:  
  26.     virtual string getname()  
  27.     {  
  28.         return string("chinese or english name? I donot know");  
  29.     }  
  30. };  
  31.   
  32. int main()  
  33. {  
  34.     Name n;  
  35.     ChineseName & c = n;  
  36.     EnglishName & e = n;  
  37.   
  38.     cout << n.getname() << endl;  
  39.     cout << c.getname() << endl;  
  40.     cout << e.getname() << endl;  
  41.   
  42.     return 0;  
  43. }  

三个输出都是一样的, 可是我怎么才能在c.getname()中输出中文名, e.getname()中输出英文名呢, 最根本的问题是我只能在Name中实现一个getname(), 但是它却被要求有两个功能, 分别输出中文名和英文名, 这着实没办法

"计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决",现在我们就通过增加两个中间类来试试

我们用两个抽象类来分别继承ChinessName和EnglishName, 它们分别重新实现getname(), getname()的实现方式相同, 都是通过NVI手法来做的(尽管getname()不是non-virtual函数), 它们分别调用两个非同名的纯虚函数, 然后再让Name继承这两个中间类, 具体实现看代码:

  1. #include <string>  
  2. #include <iostream>  
  3. using namespace std;  
  4.   
  5. class ChineseName  
  6. {  
  7. public:  
  8.     virtual string getname()  
  9.     {  
  10.         return string();  
  11.     }  
  12. };  
  13.   
  14. class EnglishName  
  15. {  
  16. public:  
  17.     virtual string getname()  
  18.     {  
  19.         return string();  
  20.     }  
  21. };  
  22.   
  23. class ICName : public ChineseName  
  24. {  
  25. public:  
  26.     virtual string getname()  
  27.     {  
  28.         return getChineseName();  
  29.     }  
  30.   
  31. private:  
  32.     virtual string getChineseName() = 0;  
  33. };  
  34.   
  35. class IEName : public EnglishName  
  36. {  
  37. public:  
  38.     virtual string getname()  
  39.     {  
  40.         return getEnglishName();  
  41.     }  
  42.   
  43. private:  
  44.     virtual string getEnglishName() = 0;  
  45. };  
  46.   
  47. class Name : public ICName, public IEName  
  48. {  
  49. private:  
  50.     virtual string getChineseName()  
  51.     {  
  52.         return string("二斗墨汁");  
  53.     }  
  54.   
  55.     virtual string getEnglishName()  
  56.     {  
  57.         return string("Adward Ink");  
  58.     }  
  59. };  
  60.   
  61. int main()  
  62. {  
  63.     Name n;  
  64.     ChineseName & c = n;  
  65.     EnglishName & e = n;  
  66.   
  67. //  cout << n.getname() << endl;  
  68.     cout << c.getname() << endl;  
  69.     cout << e.getname() << endl;  
  70.   
  71.     return 0;  
  72. }  

上面的代码运行可以分别得到中文名和英文名, 但你也应该看到这句注释掉的代码: cout << n.getname() << endl; 是的, 它不能通过编译, 它会产生二义性, 因为它不知道调用的是从ICName还是从IEName继承下来的getname(), 但为什么第一份代码又可以呢? 其实我当初也以为会产生二义, 谁知没有, 不过从测试上分析, 可知: 一份getname()已经重写了两个基类的getname()的实现

如上我们可以用Name对象直接调用ChineseName和EnglishName中所有除getname()以为的功能接口, 如果我们想分别想得到中文名和英文名怎么办? 方法一同上代码, 先转化为对应基类的引用再调用getname(), 方法二把getChineseName()和getEnglishName()改成公有的, 直接调用这两个函数

第二份代码的实现, 得助于从网上得来的一份华为学习资料(几年前看资料学过来的技术, 原资料也被遗弃了), 感谢华为

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
HTC G10 Desire-HD 2.3.5图文刷机教程
使用知云阅读器翻译《统计遗传学》书籍
Doxygen简单经验谈。。。
C#词汇表
管道图纸常规英文代码中文含义
一名合格的电子工程师,英文水平应该达到什么标准?
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服