您的位置:首页 > 编程语言 > C语言/C++

C++多态

2013-11-01 18:48 197 查看
多态的概念 :关于多态,好几种说法,好的坏的都有,分别说一下:
1 指同一个函数的多种形态。
个人认为这是一种高手中的高手喜欢的说法,对于一般开发人员是一种差的不能再差的概念,简直是对人的误导,然人很容易就靠到函数重载上了。以下是个人认为解释的比较好的两种说法,意思大体相同:
2多态是具有表现多种形态的能力的特征,在OO中是指,语言具有根据对象的类型以不同方式处理之,特别是重载方法和继承类这种形式的能力。
这种说法有点绕,仔细想想,这才是C++要告诉我们的。3多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。多态性在Object Pascal和C++中都是通过虚函数(Virtual Function) 实现的。官方,也是更准确的对多态作用的描述:
多态性使得能够利用同一类(基类)类型的指针来引用不同类的对象,以及根据所引用对象的不同,以不同的方式执行相同的操作。把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作(也就是可以调用子对象中对父对象的相关函数的改进方法)。

C++中的多态(虽然多态不是C++所特有的,但是C++中的多态确实是很特殊的)分为静多态和动多态(也就是静态绑定和动态绑定两种现象),静动的区别主要在于这种绑定发生在编译期还是运行期,发生在编译期的是静态绑定,也就是静多态;发生在运行期的则是动态绑定,也就是动多态。  静多态可以通过模板和函数重载来实现(之所说C++中的多态主要还是因为模板这个东西),下面举两个例子: 1)函数模板 template <typename T> T max(const T& lsh, const T& rhs)  {        return (lsh > rhs) ? lsh : rhs; } 返回两个任意类型对象的最大值(对象),前提是该类型能够使用>运算符进行比较,并且返回值是bool类型。 使用: int a = 3; int b = 4; cout << max(a, b) << endl; float c = 2.4; float 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),这种现象就是动多态!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: