现在的位置: 首页 > 综合 > 正文

函数的重写

2013年09月01日 ⁄ 综合 ⁄ 共 1618字 ⁄ 字号 评论关闭

我在OOP方面的知识一直都使用后再看理论的,因为之前的理论大多都没有吸收,也缺乏深入理解。最近又重新学习了继承体系中关于类中方法的重写(override)。先通过在C++下的例子来阐述这一机制。

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

class People{
public:
    People(string name){
        this->name = name;
    }
//  void display(){                //不加virtual是普通成员函数
    virtual void display(){        //加virtual变成虚函数
        cout << "I am a people, name: " + name << endl;
    };
protected:
    string name;
};

class Man : public People{
public:
    Man(string name, string wife):People(name){
        this->wife = wife;
    }
    void display(){
        cout << "I am a man, name: " + name + " wife: " + wife << endl;;
    };
protected:
    string wife;
};
int main(){
//    People p("baobei");
//    p.diplay();                    //输出:I am a people, name: baobei
//    Man m("baobei", "mbaobei");
//    m.diplay();                    //输出:I am a man, name: baobei wife: mbaobei
    
    People *p;
    p = new Man("baobei", "mbaobei");
    p->display();                    //输出:I am a man, name: baobei wife: mbaobei
    return 0;
}


在上例中,函数display()不加virtual只是普通的成员函数,那么即使在Man继承People后重写了display(),那么在主函数中父类指针p指向子类对象,并调用其函数display(),并没有执行子类对象的display()函数,而是执行了基类的方法。而在基类People中display()函数前加上virtual后,程序则调用了子类的display()方法。

这就是虚函数在动态绑定中的作用。一个基类指针指向他的任何子类对象,都能够非常智慧的执行子类的方法,而不会被父类的方法所覆盖。这种需求在OOP中是非常普遍的。几乎每个程序员每天都在用吧。


疑问一:很多人都会问,在基类中不加virtual,子类依旧可以重写,而且编译没错,程序也能执行啊?

回答:那是你没读上面那个程序,如果不加virtual,子类方法肯定就被父类方法覆盖了,除非你专门弄一个对子类对象的直接引用。


疑问二:java程序员又会说,java中子类就可以任意重写父类实现著名的父类引用指向子类对象,调用子类方法,实现动态绑定。还不用什么virtual关键字?

回答:那还是你对java语言不熟悉,java中对应的关键字是"@override",呵呵,现在知道"@override"的作用了吧,以前一直都不管那个关键字。你试着将"@override"去掉看看,父类方法必然覆盖掉子类方法,也就是父类引用只能掉父类的方法,即使他指向子类对象。


疑问三:override是重写,那么overload是什么?两者有关系么?很多人容易混?

回答:override是子类重写父类的方法实现动态绑定。是继承体系中纵向的,而overload是函数重载,横向的,类体内部的。没什么关系。但都是多态的体现!

抱歉!评论已关闭.