略谈多态

来源:互联网 发布:秋水到底喜欢谁知乎 编辑:程序博客网 时间:2024/05/21 11:03

一般在程序员的面试中,公司都会要求考察一些面向对象编程(OOP)和设计,以及候选人对一些基本概念的理解。多态是一个经常会被问到的概念。多态这个概念在软件开发中太常见了,也是很多系统设计和设计模式的基础。而且很多编程语言,已经把多态作为一种缺省的设定。例如在JAVA中,类成员函数缺省就定义成虚函数,具有多态特性。所以要是说哪个程序员不知道多态的概念,真的要去面壁了。

然而在以前的面试中,我发现很多候选人并没有把多态的概念弄得特别清楚,所以无法很好的解释其原理和应用。一般比较典型的回答,都是说基类中定义了一个方法(成员函数),而不同的派生类都有其各自的实现。这个时候我都会让候选人用一个实例来进行说明,大部分答案都会如下:

class Animal {
public:
    virtual void cry() {
        cout << "Cry" << endl;
    }

    Animal() {}
    virtual ~Animal() {}
};

class Dog :public Animal {
public:
    virtual void cry() {
        cout << "Wong" << endl;
    }

    Dog() {}
    virtual ~Dog() {}
};

class Cat :public Animal {
public:
    virtual void cry() {
        cout << "Miao" << endl;
    }

    Cat() {}
    virtual ~Cat() {}
};

很明显,这样的回答是不完整的。我一般会追问,“那么什么是重载呢?”。一般人会考虑过后,发现之前给出的多态的例子,怎么也是一个重载的例子?于是大部分人会陷入沉思。所以,要真正理解和解释多态,只有上面几个虚函数的定义是不够的,需要看看是如何使用它们的:

int main(int argc, char *argv[])
{
    Dog* dog = new Dog();
    dog->cry();
    Animal* animal = dog;
    animal->cry();
    delete dog;
    return 0;
}

上面的代码中,cry方法的第一次调用就是调用的重载方法。虽然基类Animal定义了该函数,但是由于Dog类重载了cry方法,所以dog->cry实际上调用的是Dog类的方法,而不是基类的方法。对于第二个调用cry方法的地方,就是一个典型的多态的例子。多态的表现在于,通过基类指针(或引用)调用某一个虚函数,实际上调用的函数由对象实例化的类决定的。所以虽然是通过Animal类的指针调用cry方法,但是实际上调用的是Dog类的cry方法。这里就是一种调用方式(通过Animal指针调用cry),可能有不同的调用结果或多种形态(可能是Animal、Dog或Cat类的cry方法)。这样就可以完整的解释了多态。


0 0
原创粉丝点击