当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(下) 在之前的两篇文章中,基本上介绍了如何录制脚本和生成并发用户,同时还对测试报告中的几个图表做了简单的说明.今天这篇文章做为这个系列的最后一篇,将会介绍 ...
随机推荐
- Web应用安全十大主动安全措施
这几天有空参加了360主办的第一届互联网安全大会(ISC 2013),除了现场看到FREEBUF现场微博号发的众多妹子之外,也听到了很多有趣的议题,比如TK分享的通过网络运营商缓存服务器偷渡,只需一台 ...
- XObject.java 对象还没写完,希望电脑不会丢失。坏笑,早点见。
/*面向对象强调的是对象, 面向过程强调的是功能行为,打开行为,关闭行为,执行行为,把多个行为封装成对象执行更强大的功能就是面向对象,是把多个函数, 多 个行为封装在一起,单一的函数执行对象的功能太困 ...
- Windows添加和取消右键管理员权限
亲测可用 新建文本文档,粘贴下列代码 Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\*\shell\runas]@="管理员取 ...
- 关于sysprocesses表各字段的作用
sysprocesses 表中保存关于运行在 Microsoft® SQL Server™ 上的进程的信息.这些进程可以是客户端进程或系统进程.sysprocesses 只存储在 master 数据库 ...
- sublime简书安装配置
sublime-text3编辑器 安装 sudo add-apt-repository ppa:webupd8team/sublime-text-3 sudo apt-get update sudo ...
- 用Runtime.getRuntime().exec()需要注意的地方
有时候我们可能需要调用系统外部的某个程序,此时就可以用Runtime.getRuntime().exec()来调用,他会生成一个新的进程去运行调用的程序. 此方法返回一个java.lang.Proce ...
- HTML中强大的input标签属性
用了许久的html,<input>这个标签是最常用的标签之一. <input type="">标签中type属性是必不可少的,以往我最常用的有 type=& ...
- jQuery LigerUI V1.2.2 (包括API和全部源码) 发布
前言 这次版本主要对树进行了加载性能上面的优化,并解决了部分兼容性的问题,添加了几个功能点. 欢迎使用反馈. 相关链接 API: http://api.ligerui.com/ 演示地 ...
- 处理xml c#
using System.Xml; using System; using System.Text; using System.Net; using System.Collections; using ...
- centos 7 下安装numpy、scipy等python包
本文适用于刚入门的小白,欢迎大牛们批评指正. 因为要开始数据分析,而python又不像R和matlab那么简洁.需要安装的包很多~ 网上找了好多牛人博客,想在centos7下安装numpy,scipy ...