当C++多继承遇上类型转换[转]
1 由来
2 原型与问题
- #include <iostream>
- #include <hash_map>
- using namespace std;
- class I1
- {
- public:
- virtual void vf1()
- {
- cout << "I'm I1:vf1()" << endl;
- }
- };
- class I2
- {
- public:
- virtual void vf2()
- {
- cout << "I'm I2:vf2()" << endl;
- }
- };
- class C : public I1, public I2
- {
- private:
- hash_map<string, string> m_cache;
- };
- I1* CreateC()
- {
- return new C();
- }
- int main(int argc, char** argv)
- {
- I1* pI1 = CreateC();
- pI1->vf1();
- I2* pI2 = (I2*)pI1;
- pI2->vf2();
- delete pI1;
- return 0;
- }
#include <iostream>
#include <hash_map>
using namespace std; class I1
{
public:
virtual void vf1()
{
cout << "I'm I1:vf1()" << endl;
}
}; class I2
{
public:
virtual void vf2()
{
cout << "I'm I2:vf2()" << endl;
}
}; class C : public I1, public I2
{
private:
hash_map<string, string> m_cache;
}; I1* CreateC()
{
return new C();
} int main(int argc, char** argv)
{
I1* pI1 = CreateC();
pI1->vf1(); I2* pI2 = (I2*)pI1;
pI2->vf2(); delete pI1;
return 0;
}
3 分析
- int main(int argc, char** argv)
- {
- I1* pI1 = CreateC();
- pI1->vf1();
- I2* pI2 = (I2*)pI1;
- pI2->vf2();
- cout << "pI1指向的地址为:"<<std::hex << pI1 << endl;
- cout << "pI2指向的地址为:"<<std::hex << pI2 << endl;
- delete pI1;
- return 0;
- }
int main(int argc, char** argv)
{
I1* pI1 = CreateC();
pI1->vf1(); I2* pI2 = (I2*)pI1;
pI2->vf2(); cout << "pI1指向的地址为:"<<std::hex << pI1 << endl;
cout << "pI2指向的地址为:"<<std::hex << pI2 << endl;
delete pI1;
return 0;
}
执行结果为:
- #include <iostream>
- #include <hash_map>
- using namespace std;
- class I1
- {
- public:
- virtual void vf1()
- {
- cout << "I'm I1:vf1()" << endl;
- }
- };
- class I2
- {
- public:
- virtual void vf2()
- {
- cout << "I'm I2:vf2()" << endl;
- }
- virtual void vf3()
- {
- cout << "I'm I2:vf3()" << endl;
- }
- };
- class C : public I1, public I2
- {
- private:
- hash_map<string, string> m_cache;
- };
- I1* CreateC()
- {
- return new C();
- }
- int main(int argc, char** argv)
- {
- I1* pI1 = CreateC();
- pI1->vf1();
- I2* pI2 = (I2*)pI1;
- pI2->vf2();
- pI2->vf3();
- cout << "pI1指向的地址为:"<<std::hex << pI1 << endl;
- cout << "pI2指向的地址为:"<<std::hex << pI2 << endl;
- delete pI1;
- return 0;
- }
#include <iostream>
#include <hash_map>
using namespace std; class I1
{
public:
virtual void vf1()
{
cout << "I'm I1:vf1()" << endl;
}
}; class I2
{
public:
virtual void vf2()
{
cout << "I'm I2:vf2()" << endl;
}
virtual void vf3()
{
cout << "I'm I2:vf3()" << endl;
}
}; class C : public I1, public I2
{
private:
hash_map<string, string> m_cache;
}; I1* CreateC()
{
return new C();
} int main(int argc, char** argv)
{
I1* pI1 = CreateC();
pI1->vf1(); I2* pI2 = (I2*)pI1;
pI2->vf2();
pI2->vf3(); cout << "pI1指向的地址为:"<<std::hex << pI1 << endl;
cout << "pI2指向的地址为:"<<std::hex << pI2 << endl;
delete pI1;
return 0;
}
4 解决思路
- int main(int argc, char** argv)
- {
- I1* pI1 = CreateC();
- pI1->vf1();
- I2* pI2 = dynamic_cast<I2*>(pI1);
- pI2->vf2();
- delete pI1;
- return 0;
- }
int main(int argc, char** argv)
{
I1* pI1 = CreateC();
pI1->vf1(); I2* pI2 = dynamic_cast<I2*>(pI1);
pI2->vf2(); delete pI1;
return 0;
}
此时,编译和运行都如预期一样,完全正确。缺陷就是开启RTTI会影响程序性能,而且好像VC++6中无法正常工作。
- #include <iostream>
- #include <hash_map>
- using namespace std;
- class I1
- {
- public:
- virtual void vf1()
- {
- cout << "I'm I1:vf1()" << endl;
- }
- };
- class I2
- {
- public:
- virtual void vf2()
- {
- cout << "I'm I2:vf2()" << endl;
- }
- virtual void vf3()
- {
- cout << "I'm I2:vf3()" << endl;
- }
- };
- class C : public I1, public I2
- {
- private:
- hash_map<string, string> m_cache;
- };
- I1* CreateC()
- {
- return new C();
- }
- I2* QueryInterface(I1* obj)
- {
- C* pC = static_cast<C*>(obj);
- return static_cast<I2*>(pC);
- }
- I1* QueryInterface(I2* obj)
- {
- C* pC = static_cast<C*>(obj);
- return static_cast<I1*>(pC);
- }
- int main(int argc, char** argv)
- {
- I1* pI1 = CreateC();
- pI1->vf1();
- I2* pI2 = QueryInterface(pI1);
- pI2->vf2();
- delete pI1;
- return 0;
- }
#include <iostream>
#include <hash_map>
using namespace std; class I1
{
public:
virtual void vf1()
{
cout << "I'm I1:vf1()" << endl;
}
}; class I2
{
public:
virtual void vf2()
{
cout << "I'm I2:vf2()" << endl;
}
virtual void vf3()
{
cout << "I'm I2:vf3()" << endl;
}
}; class C : public I1, public I2
{
private:
hash_map<string, string> m_cache;
}; I1* CreateC()
{
return new C();
} I2* QueryInterface(I1* obj)
{
C* pC = static_cast<C*>(obj);
return static_cast<I2*>(pC);
} I1* QueryInterface(I2* obj)
{
C* pC = static_cast<C*>(obj);
return static_cast<I1*>(pC);
} int main(int argc, char** argv)
{
I1* pI1 = CreateC();
pI1->vf1(); I2* pI2 = QueryInterface(pI1);
pI2->vf2(); delete pI1;
return 0;
}
这种方式,既可以得到正确的运行结果,也不需要用户调用dynamic_cast,所以效果最好。但实现和调用都较为麻烦,使得库的使用不方便。
5 一点感想
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace ConsoleApplication1
- {
- class Program
- {
- static void Main(string[] args)
- {
- I1 pI1 = new C();
- pI1.vf1();
- I2 pI2 = (I2)pI1;
- pI2.vf2();
- }
- }
- interface I1
- {
- void vf1();
- }
- interface I2
- {
- void vf2();
- }
- class C : I1, I2
- {
- public void vf1()
- {
- Console.WriteLine("I'm vf1()");
- }
- public void vf2()
- {
- Console.WriteLine("I'm vf2()");
- }
- }
- }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
I1 pI1 = new C();
pI1.vf1();
I2 pI2 = (I2)pI1;
pI2.vf2();
}
} interface I1
{
void vf1();
} interface I2
{
void vf2();
} class C : I1, I2
{
public void vf1()
{
Console.WriteLine("I'm vf1()");
}
public void vf2()
{
Console.WriteLine("I'm vf2()");
}
}
}
(2)开发库的时候,对外接口以类的形式是否合适?是否还是以纯粹的C函数为接口更简洁?C++的前途....
当C++多继承遇上类型转换[转]的更多相关文章
- 谁还没遇上过NoClassDefFoundError咋地——浅谈字节码生成与热部署
谁还没遇上过NoClassDefFoundError咋地--浅谈字节码生成与热部署 前言 在Java程序员的世界里,NoClassDefFoundError是一类相当令人厌恶的错误,因为这类错误通常非 ...
- MVC遇上bootstrap后的ajax表单模型验证
MVC遇上bootstrap后的ajax表单验证 使用bootstrap后他由他自带的样式has-error,想要使用它就会比较麻烦,往常使用jqueyr.validate的话只有使用他自己的样式了, ...
- 敏捷遇上UML-需求分析及软件设计最佳实践(郑州站 2014-6-7)
邀请函: 尊敬的阁下:我们将在郑州为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实 ...
- 敏捷遇上UML—软创基地马年大会(广州站 2014-4-19)
我们将在广州为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实战技巧. 时间:2 ...
- 敏捷遇上UML——软创基地马年大会(深圳站 2014-3-15)
邀请函: 尊敬的阁下: 我们将在深圳为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实战 ...
- 初识genymotion安装遇上的VirtualBox问题
想必做过Android开发的都讨厌那慢如蜗牛的 eclipse原生Android模拟器吧! 光是启动这个模拟器都得花上两三分钟,慢慢的用起来手机来调试,但那毕竟不是长久之计,也确实不方便,后来知道了g ...
- SQL SERVER 2008 R2 SP1更新时,遇上共享功能更新失败解决方案
SQL SERVER 2008 R2 SP1更新时,遇上共享功能更新失败的问题,可作如下尝试: 更新失败后,在windows的[事件查看器→应用程序]中找到来源为MsiInstaller,事件ID为1 ...
- 当创业遇上O2O,新一批死亡名单,看完震惊了!
当创业遇上O2O,故事就开始了,总投入1.6亿.半年开7家便利店.会员猛增至10万……2015半年过去后,很多故事在后面变成了一场创业“事故”,是模式错误还是烧钱过度?这些项目的失败能给国内创业者带来 ...
- LoadRunner - 当DiscuzNT遇上了Loadrunner(下) (转发)
当DiscuzNT遇上了Loadrunner(下) 在之前的两篇文章中,基本上介绍了如何录制脚本和生成并发用户,同时还对测试报告中的几个图表做了简单的说明.今天这篇文章做为这个系列的最后一篇,将会介绍 ...
随机推荐
- SpringMVC文件上传注意事项
简介 我在使用 idea 上传文件时遇到一些问题,费了好些时间,最后还是的队友来帮忙. 问题出现在没有熟练使用 IDE,采用 SpringMVC 上传文件主要注意几个事项. 1. 配置 bean 在 ...
- MVC5+EF6 入门完整教程六
本篇我们谈谈分部视图(Partial View). 上篇文章提到过Partial和Action这两个helper, 本篇文章主要就结合这两个helper来讲解分部视图(Partial View)的应用 ...
- [转]搭建高可用mongodb集群(四)—— 分片
按照上一节中<搭建高可用mongodb集群(三)—— 深入副本集>搭建后还有两个问题没有解决: 从节点每个上面的数据都是对数据库全量拷贝,从节点压力会不会过大? 数据压力大到机器支撑不了的 ...
- 滑动式折叠菜单 - Slashdot's Menu
折叠菜单让你在尽可能小的地方放置尽可能多的内容,同时加大了操作的简便性,因此,深受前台设计师的喜爱.随着大家对动画效果的钟爱,折叠菜单也开始“动”起来了,本文介绍的就是 DimX 制作的滑动式折叠菜单 ...
- javascript数组的方法总结,非常实用的!
在ES5中,一共有9个Array方法 http://kangax.github.io/compat-table/es5/ 注* 九个方法 Array.prototype.indexOfArray.pr ...
- C#最齐全的上传图片方法。
public ActionResult Upload() { string imgurl = ""; foreach (string key in Request.Files) { ...
- linux 下安装PHP的IMAP扩展实现邮件收发
系统CentOS 6.5 PHP5.5.19 1.安装imap的依赖包: [root@iZ9482lp6yqZ]# yum install -y libc-client-* 没有安装编译错误提示: ...
- Linux 文件访问权限
定义:<sys/stat.h> 每个文件有9个访问权限,可将其分为3类: 标记 含义 S_IRUSR 用户读 S_IWUSR 用户写 S_IXUSR 用户执行 S_IRGRP 组读 S_I ...
- iOS中 HTTP/Socket/TCP/IP通信协议详解
// OSI(开放式系统互联), 由ISO(国际化标准组织)制定 // 1. 应用层 // 2. 表示层 // 3. 会话层 // 4. 传输层 // 5. 网络层 // 6. 数据链接层 // 7. ...
- 如何快速掌握一款新的MCU? (转)
发布时间:2013-12-15 10:27:51 技术类别:单片机 个人分类:话题思考 任何一款MCU,其基本原理和功能都是大同小异,所不同的只是其外围功能模块的配置及数量.指 ...