当前位置:编程学习 > C/C++ >>

C++学习之多态

C++的类机制中有支持多态的技术来解决抽象编程,它用的是一种滞后捆绑技术,
这种技术,通过预先设定其成员函数的虚函数性质,使得任何捆绑该成员函数的未定类型的对象操作在编译时,都以一个不确定的指针特殊地“引命代发”来编码,
到了运行时,遇到确定类型的对象,才突然制定其真正的行为。即滞后到运行时,根据具体类型的对象来捆绑成员函数,这样,辨别对象类型的工作就可以不用用户做了。

虚函数(Virtual Function)
1.多态条件(Polymorphism Condition)
使用类编程中,要能进行抽象编程,不随类的改动而改动,类机制必须解决这个问题,在C++中,就是虚函数机制。基类与派生类的同名操作。只要标记上virtual,则该操作便具有多态性。
如下代码所示:

[cpp] 
#include <iostream> 
using namespace std; 
 
class Base 

public: 
    virtual void fun() 
    { 
        cout << "In Base class" << endl; 
    } 
}; 
 
class Sub : public Base 

public: 
    virtual void fun() 
    { 
        cout << "In Sub class" << endl; 
    } 
}; 
 
void test(Base& b) 

    b.fun(); 

 
int main() 

    Base bc; 
    Sub sc; 
    test(bc); 
    test(sc); 
 
    return 0; 

代码输出如下:

[plain] 
In Base class 
In Sub class 

 

上述代码中fun是Base类的虚函数,一旦标记了基类的函数为虚函数,则后面继承类中一切同名成员函数都编程了虚函数,在test函数中,b是Base类的引用性形参,Base类对象和Sub类对象都可以作为实参传给形参b。

 

如果函数参数是实际复制动作的传递,则子类对象完全变成基类对象了,这样,便不会有多态了。如将上述代码中的test函数参数改为如下形式时,

如下代码所示:

[cpp] 
void test(Base b) 

    b.fun(); 

 
int main() 

    Base bc; 
    Sub sc; 
    test(bc); 
    test(sc); 
 
    return 0; 

其输出则变为:

[plain] 
In Base class 
In Base class 

因为对于这种参数的传递过程已经将对象的性质做了肯定的转变,而对于确定的对象,是没有选择操作可言的。因此,对于多态,仅仅对于对象的指针和引用的间接访问,才会发生多态现象。

 

2. 虚函数机理

在上述代码中,b.fun()函数调用显示出多样性,其编译不能立即确定fun的确切位置,即不能确定到底是调用基类Base的fun函数,还是子类Sub的fun函数。

当编译器看到fun的虚函数标志时,以放入虚函数表中,等到遇到b.fun()这个虚函数的调用时,便将该捆绑操作滞后到运行中,以实际的对象类型来实际捆绑其对应的成员函数操作。当然编译器不可能跟踪到运行的程序中去,而是在捆绑操作b.fun()处避开函数调用,只做一个指向实际对象的成员函数的间接访问。如此,实际对象若是基类,则调用的就是基类成员函数,若是子类,则调用的就是子类的成员函数。当然,每一个实际的对象都必须额外占有一个指针空间,以指向类中的虚函数表。如下图所示。

 

从图中可以看处,用了虚函数的类,其对象的空间比不用虚函数的类多了一个指针的空间,由于涉及了其他的操作,包括间接访问虚函数,对象的指针偏移量计算等,所以在应用了虚函数后,会影响程序的运行效率。

 

3.虚函数的传播

虚函数在继承层次结构中总是会自动地从基类传播下去。因此,上述代码中Sub类中的成员函数fun的virtual说明可以省略,

例如下面的例子:

在一个平面形状类的体系中,基类shape有两个子类:圆Circle类和长方形Retangle类,专门负责求面积的Area函数在基类中设置为virtual就能使子类的响应同名函数虚拟化。

[plain] 
#include<iostream> 
#include <cmath> 
 
using namespace std; 
 
class Shape 

protected: 
    double xCoord, yCoord; 
public: 
    Shape(double x, double y) 
    { 
        xCoord = x; 
        yCoord = y; 
    } 
    virtual double area()const 
    { 
        return 0.0; 
    } 
}; 
 
class Circle : public Shape 

protected: 
    double radius; 
public: 
    Circle(double x, double y, double r) : Shape(x, y) 
    { 
        radius = r; 
    } 
    double area()const 
    { 
        return 3.14 * radius * radius; 
    } 
}; 
 
class Rectangle : public Shape 

protected: 
    double x2Coord, y2Coord; 
public: 
    Rectangle(double x1, double y1, double x2, double y2) : Shape(x1, y1) 
    { 
        x2Coord = x2; 
        y2Coord = y2; 
    } 
    double area()const; 
}; 
 
double Rectangle::area()const 

    return abs((xCoord - x2Coord) * (yCoord - y2Coord)); 

 
void fun(const Shape& sp) 

    cout << sp.area() << endl; 

 
int main() 

    fun(Circle(2, 5, 4)); 
    fun(Rectangle(2, 4, 1, 2)); 
 
    return 0; 

补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,