E-Dreamer

脚踏实地,仰望星空

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

多态 (参考:https://www.cnblogs.com/alinh/p/9636352.html

概念: 同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。

  对于C++中的多态:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数,如果对象类型是派生类,就调用派生类的函数,如果对象类型是基类,就调用基类的函数。

重写与重载: 

重写——指派生类中存在重新定义的函数。其函数名,参数列表,返回值类型,所有都必须同基类中被重写的函数一致。只有函数体不同(花括号内),派生类调用时会调用派生类的重写函数,不会调用被重写函数。重写的基类中被重写的函数必须有virtual修饰。

重载——指同一可访问区内被声明的几个具有不同参数列(参数的类型,个数,顺序不同)的同名函数,根据参数列表确定调用哪个函数,重载不关心函数返回类型。

实现多态的方法

1. C++中通过重载函数的方法可以在编译期间实现多态。

int Add(int left, int right){
    return left + right;}
double Add(double left, int right){
    return left + right;}
int main(){
    Add(10, 20);
    Add(10.0,20);  //正常代码
    return 0;}

2.使用虚函数实现多态

#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
using namespace std;
class Father
{
public:
    void Face()
    {
        cout << "Father's face" << endl;
    }
    virtual void Say()  // 虚函数
    {
        cout << "Father say hello" << endl;
    }
};
class Son:public Father
{
public:    
    void Say()
    {
        cout << "Son say hello" << endl;
    }
};
void main()
{
    Son son;
    Father *pFather=&son; // 隐式类型转换
    pFather->Say(); // Son say hello
}  

再举一个碰到的题目为例:

using namespace std;
class A{
    public:
        virtual void f() { cout << "A::f() "; }
        void f() const { cout << "A::f() const "; }
};
class B : public A {
    public:
        void f() { cout << "B::f() "; }
        void f() const { cout << "B::f() const "; }
};
void g(const A* a) {
    a->f();
}
int main(int argc, char *argv[]) {
    A* p = new B();
    p->f();
    g(p);
    delete(p);
    return 0;
}

问: 上面程序的输出是?

 B::f() A::f() const

解释:

  常量指针指向常对象, 常对象只能调用其常成员函数,因此通过g(const A* a)调用的是void f() const;
  由于f()在基类中声明为虚的,则p->f()根据对象类型(B)调用B::f(),此时编译器对虚方法使用动态联编(多态),输出B::f()。
  由于f() const在基类中未声明为虚的,故p->f() const 根据指针类型(A)调用A::f() const,此时编译器对非虚方法使用静态联编,输出A::f() const。
 
posted on 2020-05-16 11:18  E-Dreamer  阅读(281)  评论(0编辑  收藏  举报