静多态可以通过模板和函数重载来实现(之所说C++中的多态主要还是因为模板这个东西),下面举两个例子:
1)函数模板
template <typename T>
T max(const T&lsh, const T&rhs)
{
return (lsh >rhs) ? lsh : rhs
}
返回两个任意类型对象的最大值(对象),前提是该类型能够使用>运算符进行比较,并且返回值是bool类型。
使用:
int a = 3int b = 4
cout <<max(a, b) <<endl
float c = 2.4float d = 1.2
cout <<max(c, d) <<endl
输出结果为:
4
2.4
这种绑定发生在编译期,这是由于模板的实例化是发生在编译期的,即在编译时编译器发现你调用max(a, b)时就自动生成一个函数
int max(const int&lsh, const int&rhs)
{
return (lsh >rhs) ? lsh : rhs
}
即将所有的T替换成int
当你调用max(c, d)时就自动生成一个函数
float max(const float&lsh, const float&rhs)
{
return (lsh >rhs) ? lsh : rhs
}
之所以说开始的函数定义是函数模板,就是因为他就像个模子似的,你可以用铝作为原料也可以用石膏或者铜。
2)函数重载:
int max (int a, int b)
{
return (a >b) ? a : b
}
int max (int a, int b, int c)
{
return max(max(a, b), c)
}
两个函数名称一样,参数类型或个数不完全相同,返回值一样(这个不重要)。
使用:
int a = 3, b = 4, c = 5
cout <<max(a, b) <<endl
cout <<max(a, b, c) <<endl
输出结果为:
4
5
确定函数的过程也发生在编译器,当你使用max(a, b),编译器发现只有两个参数,那么就调用只有两个参数的函数版本,当使用max(a, b, c)时,编译器则使用有3个参数的版本。
通过上面的两个例子,你还可以使用更为方便的模板函数重载:
template <typename T>
T max(const T&lsh, const T&rhs)
{
return (lsh >rhs) ? lsh : rhs
}
template <typename T>
T max(const T&a, const T&b, const T&c)
{
return max(max(a, b), c)
}
使用
float a = 3.6, b = 1.2, c = 7.8
cout <<max(a, b, c) <<endl
输出:
7.8
通过参数个数和类型,编译器自动生成和调用对应得函数版本!
动多态则是通过继承、虚函数(virtual)、指针来实现。
class A {
public:
virtual void func() const {
coust <<“A::func()” <<endl
}
}
class B : public A {
public:
virtual void func() const {
coust <<“B::func()” <<endl
}
}
使用:
A a* = B()
a->func()
输出:
B::func()
编译期是不调用任何函数的,编译器编译到a->func()时只是检查有没有语法问题,经过检查没有。编译器并不知道调用的是A版本的func()还是B版本的func(),由于a是一个指向B对象的指针,所以a只知道它指向的是一个A类型(或者能转换成A类型)的对象。通常集成体系就说明了(由于是公有继承)B是一种A。在运行期,a要调用a所指向对象的func()函数,就对它指向的对象下达调用func()的命令,结果a所指向的是一个B对象,这个对象就调用了自己版本(B版)的func()函数,所以输出时B::func()
总结:
在编译期决定你应该调用哪个函数的行为是静态绑定(static-binding),这种现象就是静多态。
在运行期决定应该调用哪中类型对象的函数的行为是动态绑定(dynamic-binding),这种现象就是动多态
using System//调用system类 和C下的include一样using System.Drawing//调用system.drawing类
using _05_Base //调用自建类05_base
namespace _05_03 //命名空间 05_03
{
public class Class_05_03 //公有类05_03
{
public static void PrintArea(Shape shape)
//公有类 静态 无返回值类 PrintArea(内部数据成员shape,把shape这个单词指定为shape类型,就象int i)
{
Console.WriteLine("Area of {0} is : {1}", shape.Name, shape.Area)
//控制台输出 Area of {0} is : {1} 其中0为shape.Name的数据 1 为shape.Area的数据
}
public static void Main(String[] args)
// 公有类 静态无返回值 主函数()
{
Point p = new Point(0, 0)
为point 分配一新的空间p(0,0)
_05_Base.Rectangle r = new _05_Base.Rectangle()
// 分配一新的空间r ,用05_Base.Rectangle类化
r.Name = "Rectangle r"
r.Width = 10
r.Height = 20
//以上3行为新分配的空间r 写入其类的对应值
Square s = new Square()
s.Name = "Square s"
s.Side = 15
//用Square 类化s 分配空间 赋值
Ellipse e = new Ellipse()
e.Name = "Ellipse e"
e.SemiMajorAxis = 10
e.SemiMinorAxis = 5
//用Ellipse类化e 分配空间 赋值
Circle c = new Circle()
c.Name = "Circle c"
c.Radius = 6
Triangle t = new Triangle()
t.Name = "Triangle t"
t.Point1 = new Point(3, 3)
t.Point2 = new Point(3, 0)
// 这两个自己会看了把??
Shape[] shapes = new Shape[5]
shapes[0] = r
shapes[1] = s
shapes[2] = e
shapes[3] = c
shapes[4] = t
foreach(Shape shape in shapes)
//Shape shape in shapes不懂这是什么意思
{
shape.Position = p
PrintArea(shape)
}
}
}
}
在C++中: classA{public: A(){} virtual void foo() { cout<<ThisisA.<<endl }}classB:publicA{public: B(){} void foo() { cout<<ThisisB.<<endl }}int main(intargc,char*argv[]){ A* a = new B() a->foo() if(a != NULL) delete a return0}这将显示:
This is B.
如果把virtual去掉,将显示:
This is A.
前面的多态通过使用虚函数virtual void foo()来实现。
在java中:
多态,是面向对象的程序设计语言最核心的特征。多态,意味着一个对象有着多重特征,可以在特定的情况下,表现不同的状态,从而对应着不同的属性和方法。从程序设计的角度而言,多态可以这样来实现(以java语言为例): public interface Parent//父类接口{ public void simpleCall()}public class Child_A implements Parent{ public void simpleCall() { //具体的实现细节; }}public class Child_B implements Parent{ public void simpleCall() { //具体的实现细节; }}//当然还可以有其他的实现
然后,我们就可以看到多态所展示的特性了:
Parent pa = new Child_A()
pa.simpleCall()则显然是调用Child_A的方法;
Parent pa = new Child_B()
pa.simpleCall()则是在调用Child_B的方法。所以,我们对于抽象的父类或者接口给出了我们的具体实现后,pa 可以完全不用管实现的细节,只访问我们定义的方法,就可以了。事实上,这就是多态所起的作用,可以实现控制反转这在大量的J2EE轻量级框架中被用到,比如Spring的依赖注入机制。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)