当多态遇上数组 ... [C++, C++/CLI, C#]
When Polymorphism Meets Arrays ... [C++, C++/CLI, C#]
Written by Allen Lee
犹如星空与海鸥,漫画里根本你我一生永不会聚头,但我誓要共你牵手。
—— 古巨基,《美雪,美雪》
1. 能力测试
请回答下面的问题:
上面的题目仅用于测试你是否具备阅读本文的必要条件。如果你对此题毫无头绪,那么我建议你尽快交叉本文。当然,要顺畅阅读本文,你还需要具备一些C++、C++/CLI和C#的基础知识。我想不必特别声明,建议当然是主观的。不过我愿意再说一次:建议是主观的,你有选择。
2. ... In C++,
好吧,既然你走到这一步,我建议你坚持下去。当然,你还是随时可以交叉本文,总之,你有选择。来,请先看看如下代码:
//Code#01
#include<tchar.h><br><img src="/Images/OutliningIndicators/None.gif" align="top"><span style="COLOR: #0000ff">#include</span><iostream><br><img src="/Images/OutliningIndicators/None.gif" align="top"><br><img src="/Images/OutliningIndicators/None.gif" align="top"></iostream></tchar.h>classA
{
public:
virtualvoidPrint()
{
std::cout}
};
classB:publicA
{
public:
virtualvoidPrint()override
{
std::cout}
};
classC:publicA
{
public:
virtualvoidPrint()override
{
std::cout}
};
voidPrint(Aarr[],intcount)
{
for(inti=0;i{
arr[i].Print();
}
}
int_tmain(intargc,_TCHAR*argv[])
{
constintCOUNT=11;
Aa_arr[COUNT];
Print(a_arr,COUNT);
Bb_arr[COUNT];
Print(b_arr,COUNT);
Cc_arr[COUNT];
Print(c_arr,COUNT);
return0;
}
- A:请告诉我,Code #01有没有问题?
- B:Easy job!把它编译并运行一下就知道了呗!
接着,阿B编译了这段代码,程序运行后,阿B发现输出结果正是我们所期望的。于是,阿B得出结论:这段代码没问题!
然而,你是否知道这段代码其实隐藏着一个计时,只要时机一到,它就会引爆并使你的程序完全瘫痪?不信?那我只好让你见识一下这个引爆是的情景了。现在,我分别为class B和class C加入一个field,并修改一下main()以便给class B和class C里的field赋值(注意,本赋值操作不是必须的!):
//Code#02
#include<tchar.h><br><img src="/Images/OutliningIndicators/None.gif" align="top"><span style="COLOR: #0000ff">#include</span><iostream><br><img src="/Images/OutliningIndicators/None.gif" align="top"><br><img src="/Images/OutliningIndicators/None.gif" align="top"></iostream></tchar.h>classA
{
public:
virtualvoidPrint()
{
std::cout}
};
classB:publicA
{
public:
virtualvoidPrint()override
{
std::cout}
longL;
};
classC:publicA
{
public:
virtualvoidPrint()override
{
std::cout}
doubleD;
};
voidPrint(Aarr[],intcount)
{
for(inti=0;i{
arr[i].Print();
}
}
int_tmain(intargc,_TCHAR*argv[])
{
constintCOUNT=11;
Aa_arr[COUNT];
Print(a_arr,COUNT);
Bb_arr[COUNT];
for(inti=0;i{
b_arr[i].L=141214121412;
}
Print(b_arr,COUNT);
Cc_arr[COUNT];
for(inti=0;i{
c_arr[i].D=3.141592654;
}
Print(c_arr,COUNT);
return0;
}
计时终于被引爆了:
可见程序无法找到b_arr[1]确切位置,其后果不会好过你在街上把一个背影看似相熟的女性误认为是你的女朋友时所产生的尴尬。至于产生这个问题的原因,Scott Meyers已经在他的《More Effective C++》作了详细的讲解[1],这里我就没必要重复劳动了。
显然,产生这个问题的根本原因是数组里的存放物长度不一致,如果能够让存放物的长度统一起来,问题就会迎刃而解了。问题男提出把指针放进数组,好吧,现在我们来看一下C++中多态与数组牵手的景象:
//Code#02'
//SeeCode#02forClassA,ClassBandClassC.
voidPrint(A*arr[],intcount)
{
for(inti=0;i{
arr[i]->Print();
}
}
int_tmain(intargc,_TCHAR*argv[])
{
constintCOUNT=11;
A**a_arr=newA*[COUNT];
B**b_arr=newB*[COUNT];
C**c_arr=newC*[COUNT];
for(inti=0;i{
a_arr[i]=newA;
b_arr[i]=newB;
b_arr[i]->L=141214121412;
c_arr[i]=newC;
c_arr[i]->D=3.141592654;
}
Print(a_arr,COUNT);
Print(reinterpret_cast(b_arr),COUNT);
Print(reinterpret_cast(c_arr),COUNT);
return0;
}
问题解决了,不过,我还是强烈建议你(当然,你有选择!):
在C++中,请尽量使用STL中的容器类来协助实现多态的效果。
3. ... In C++/CLI,
在C++/CLI的托管类型(Managed Type)中,只有ref class(或ref struct)[2]可用于建立继承体系。下面,我们来看看在C++/CLI中使用数组实现多态的情形:
//Code#03
usingnamespaceSystem;
usingnamespacestdcli::language;
refclassA
{
public:
virtualvoidPrint()
{
Console::WriteLine("A");
}
};
refclassB:publicA
{
public:
virtualvoidPrint()override
{
Console::WriteLine("B");
}
longL;
};
refclassC:publicA
{
public:
virtualvoidPrint()override
{
Console::WriteLine("C");
}
doubleD;
};
voidPrint(array^arr)
{
for(inti=0;iCount;++i)
{
arr[i]->Print();
}
}
int_tmain()
{
constintCOUNT=11;
array^a_arr=gcnewarray(COUNT);
for(inti=0;iCount;++i)
{
a_arr[i]=gcnewA;
}
Print(a_arr);
array^b_arr=gcnewarray(COUNT);
for(inti=0;iCount;++i)
{
b_arr[i]=gcnewB;
b_arr[i]->l=141214121412;
}
Print(b_arr);
array^c_arr=gcnewarray(COUNT);
for(inti=0;iCount;++i)
{
c_arr[i]=gcnewC;
c_arr[i]->d=3.141592654;
}
Print(c_arr);
}
4. ... In C#,
而在C#中,使用数组来实现多态又是如何的呢:
相关推荐
在C++/CLI中,你可以编写托管代码(运行在.NET Framework上的代码)和非托管代码(传统的C++代码)。这使得C++/CLI成为连接原生C++程序和.NET应用程序的桥梁。 3. **关键字和语法** - `ref class`:表示托管类,...
C++/CLI 详解 C++/CLI 是一种将 C++ 语言与 CLI(公共语言结构)相结合的语言,它提供了对动态组件编程模型的支持,并在保持 C++ 语言的静态对象模型的同时,提供了对 CLI 的支持。本文将详细介绍 C++/CLI 的概念、...
这是因为C++的特性如多态、构造函数等在C#中无法直接使用。纯C接口将避免这些高级特性的使用,使得接口更容易被其他语言调用。 2. **使用C++/CLI创建托管接口**:利用C++/CLI,创建一个新的项目,将声网的C++头文件...
综上所述,C,C++,C#混合编程涉及了从底层到高层的各种编程概念和技术,开发者需要深入理解每种语言的特性和局限,以实现高效的代码整合。这种编程方式在解决复杂问题和利用不同语言优势时尤为有用。
3. 面向对象特性:C++的虚函数在C#中对应为抽象方法或接口实现,继承和多态也需要相应调整。 4. 异常处理:C++使用try-catch-finally语句块,C#也有类似机制,但语法略有不同。 5. 内存管理:C++需要手动管理内存...
【标题】"C# Pro Visual C++ CLI and the .NET 3.5 Platform 2009源代码" 本资源包含的是《C# Pro Visual C++ CLI和.NET 3.5平台2009》一书的源代码,旨在帮助读者深入理解C#和Visual C++ CLI在.NET 3.5框架下的...
- **值类型**: 在C++CLI中,值类型通常是结构体(struct),它们在栈上分配内存,并且可以包含其他类型的成员。 #### 十四、接口 - **接口**: 用于定义一组相关的抽象方法和属性,可以由多个类实现。 #### 十五、...
C#和C++是两种广泛使用的编程语言,它们在软件开发领域有着深远的影响。这篇帮助文档旨在为开发者提供关于这两种语言的详细指南,以便更好地利用它们进行开发工作,特别是结合MFC(Microsoft Foundation Classes)和...
2. C#语言与C++/CLI:对比C++和C#的语法差异,学习C++/CLI,它是C++的一个扩展,用于.NET编程。 3. Windows Forms:创建基于Windows的图形用户界面,包括控件使用、布局管理和事件处理。 4. ADO.NET:.NET框架下的...
在.NET编程领域,C#是最常见的语言,但同时也支持C++/CLI,它是一种针对.NET框架的C++扩展,允许开发者利用C++语法来编写.NET应用程序。C++/CLI提供了对.NET Framework的全面访问,包括托管代码、类型系统、垃圾回收...
在.NET Framework中,C#和C++都是支持OOP的编程语言,它们提供了丰富的特性来实现这一编程模型,如类、对象、封装、继承、多态等。 1. **类与对象**:类是创建对象的模板,定义了一组属性(数据成员)和方法(行为...
.NET Framework使得跨语言开发成为可能,并且支持多种语言,如C#、VB.NET、C++/CLI等。 **C#的关键特性** 1. **面向对象编程**:C#支持类、接口、继承、多态等面向对象编程概念,让代码更加模块化和可维护。 2. *...
.NET Framework是微软的一个开发平台,它提供了一个执行环境(称为Common Language Runtime,CLR)和一组丰富的库,支持多种编程语言,包括C#、VB.NET、C++/CLI等。CLR提供了垃圾回收、类型安全、跨语言交互等服务,...
【标签】"C#" 提示了虽然主要讨论的是Visual C++.NET,但可能也涉及C#语言,因为两者在.NET平台上共存并相互协作。C#是微软为了.NET框架设计的一种现代、面向对象的编程语言,它与C++有许多相似之处,但在语法和特性...
4. **C++/CLI**:Visual C++支持C++/CLI,这是一种扩展了标准C++的语言,用于编写.NET Framework的托管代码。它可以与.NET平台的其他语言(如C#和VB.NET)无缝交互。 5. **调试工具**:Visual C++的调试器功能强大...
10. **C++与.NET Framework的结合**:了解如何使用C++/CLI(Managed Extensions for C++)编写托管代码,以及如何与.NET Framework的其他语言(如C#、VB.NET)进行交互。 总之,《Visual C++ 2005入门经典》为初学...
- C++/CLI是C++的.NET扩展,支持托管代码和非托管代码的混合编程。 - 使用`ref class`创建托管对象,与.NET框架的其他语言(如C#、VB.NET)交互。 - `gcnew`关键字代替`new`进行垃圾回收对象的分配。 5. **MFC...
19. **异构编程**:C#支持与其他语言如C++/CLI的互操作,以便利用.NET Framework的全部功能。 20. **元数据(Metadata)**:C#编译后的IL代码带有元数据,可以用于反射,动态加载和执行代码。 《C#语言规范(中文...