VC++ 之 多态性与虚函数

时间:2014-10-31 15:23:27   收藏:0   阅读:1387

多态性是面向对象程序设计的关键技术之一。利用多态性技术,可以调用同一个函数名的函数,实现完全不同的功能。若程序设计语言不支持多态性,不能称为面向对象的语言。


在C++中有两种多态性:

虚函数的定义

◆ 1、定义格式
虚函数是一个类的成员函数,定义格式如下:
    virtual 返回类型 函数名(参数表);

说明:

◆ 2、通过虚函数实现多态性
虚函数怎样实现多态性?请参见下面2个例子。

①【例8.6】计算学分。可由本科生类派生出研究生类,但它们各自的从课程学时数折算为学分数的算法是不同的,本科生是16个学时一学分,而研究生是20个学时一学分。赋值兼容规则与自定义的复制构造函数。

#include<iostream>
#include<string>
using namespace std;
class Student{
    string coursename;            //课程名
    int classhour;                    //学时
    int credit;                        //学分,未考虑0.5学分
public:
    Student(){coursename="#";classhour=0;credit=0;}
    virtual void Calculate(){credit=classhour/16;}
    void SetCourse(string str,int hour){
        coursename=str;
        classhour=hour;
    }
    int GetHour(){return classhour;}
    void SetCredit(int cred){credit=cred;}
    void Print(){cout<<coursename<<\t<<classhour<<"学时"<<\t<<credit<<"学分"<<endl;}
};
class GradeStudent:public Student{
public:
    GradeStudent(){};
    void Calculate(){SetCredit(GetHour()/20);}
};
int main(){
    Student s,*ps;
    GradeStudent g;
    s.SetCourse("物理",80);
    s.Calculate();
    g.SetCourse("物理",80);
    g.Calculate();
    cout<<"本科生:"<<\t;
    s.Print();
    cout<<"研究生:"<<\t;
    g.Print();
    s.SetCourse("数学",160);
    g.SetCourse("数学",160);
    ps=&s;
    ps->Calculate();
    cout<<"本科生:"<<\t;
    ps->Print();
    ps=&g;
    ps->Calculate();
    cout<<"研究生:"<<\t;
    ps->Print();
    getchar();
    return 0;
}

 

 



运行结果为:
本科生:物理 80学时 5学分
研究生:物理 80学时 4学分
本科生:数学 160学时 10学分
研究生:数学 160学时 8学分

分析:
第一行,学分是由Student类的成员函数Calculate()计算。
第二行,学分是由GradeStudent重新定义的Calculate()计算,它屏蔽了基类的同名函数。与不定义为虚函数一样,属编译时的多态性。
第三行,用的是指向Student类的对象s的指针,用的是Student类的Calculate()。
第四行,指针类型是指向基类的指针,但这里指针指向了派生类GradeStudent的对象g,按赋值兼容规则是准许的,但只能用基类的成员,可实际上用了派生类中新定义的Calculate()。这就是虚函数体现的多态性。如果不是虚函数,第四行输出是10学分。如果不使用基类指针指向派生类GradeStudent的对象g,也不能实现运行时的多态性。

②为体现虚函数的多态性的优点,可改造【例8.6】为

#include<iostream>
#include<string>
using namespace std;

class Student{
    string coursename;            //课程名
    int classhour;                    //学时
    int credit;                        //学分,未考虑0.5学分
public:
    Student(){coursename="#";classhour=0;credit=0;}
    virtual void Calculate(){credit=classhour/16;}
    void SetCourse(string str,int hour){
        coursename=str;
        classhour=hour;
    }
    int GetHour(){return classhour;}
    void SetCredit(int cred){credit=cred;} 
    void Print(){cout<<coursename<<\t<<classhour<<"学时"<<\t<<credit<<"学分"<<endl;}
};
class GradeStudent:public Student{
public:
    GradeStudent(){};
    void Calculate(){SetCredit(GetHour()/20);}
};

void Calfun(Student &ps,string str,int hour){
    ps.SetCourse(str,hour);
    ps.Calculate();
    ps.Print();
}
int main(){
    Student s;
    GradeStudent g;
    cout<<"本科生:";
    Calfun(s,"物理",80);
    cout<<"研究生:";
    Calfun(g,"物理",80);//派生类对象初始化基类的引用,只有calculate()为虚函数才能实现动态的多态性
    return 0;
}

 

 

运行结果为:
本科生:物理 80学时 5学分
研究生:物理 80学时 4学分

分析:
这里没有用指针,而用了Student的引用,正如在第四章中所叙述的对编译器而言引用的处理同样是通过地址间接完成的,所以引用也可以实现运行时的多态性。加了一个Calfun()函数,使用更为方便。

◆ 3、注意事项
一个类中将所有的成员函数尽可能地设置为虚函数总是有好处的,但必须注意以下几条:

 

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!