C++编程基础——继承、对象类型转换、虚函数、多态

对象类型转换

向上转型:子类类型转化为父类类型,有意义、安全、可以隐式进行。

向下转型:从父类类型转化为子类类型,不一定有意义、也不一定安全、必须由我们自己进行强制类型转换。

mutable关键字:异变的、可变的,该关键字修饰的变量总能被修改,不受 const 关键字的影响。

虚函数(Virtual Function)

用 virtual 关键字修饰的方法就是虚函数(虚方法)

当用一个父类指针或引用指向某个子类对象时,通过这个指针或引用调用父类中的某个虚函数,如果子类重写(Override)了父类中的这个虚函数,那么调用的将是子类中的那个方法,否则调用的就是父类中的方法。

方法重写(Method Override):子类中显式定义一个和父类中某个虚函数同名(方法名和形参列表均相同)的方法。

如果父类中某个方法为虚函数,那么其所有子类中与该方法同名的方法将自动都是虚函数,可以不用写 virtual 关键字。

多态(Polymorphic)

多种形态。在 面向对象编程(OOP)中,多态就是指同一种调用形式,根据实际情况不同会产生不同的执行结果。

在 C++ 中实现多态的前提:

  1. 父类指针或父类引用指向某个子类对象。
  2. 父类中必须有虚函数

实例一:多重继承

#include <iostream>
using namespace std;


class Animal
{
public:
    int id;

    Animal()
    {
        cout << "Animal()" << endl;
    }

    Animal(int id):id(id)
    {
        cout << "Animal(int)" << endl;
    }  

    ~Animal()
    {
        cout << "~Animal()" << endl;
    }

    void eat()
    {
        cout << "I can eat!" << endl;
    }
};


class Horse: virtual public Animal  // 虚继承,Animal 就是虚基类
{
public:
    int h;

    Horse()
    {
        cout << "Horse()" << endl;
    }

    Horse(int id, int h):h(h)
    {
        cout << "Horse(int)" << endl;
    }

    ~Horse()
    {
        cout << "~Horse()" << endl;
    }

    void run()
    {
        cout << "I can run fast!" << endl;
    }
};

class Donkey: virtual public Animal  // 虚继承,Animal 就是虚基类
{
public:
    int d;

    Donkey()
    {
        cout << "Donkey()" << endl;
    }

    Donkey(int id, int d):d(d)
    {
        cout << "Donkey(int)" << endl;
    }

    ~Donkey()
    {
        cout << "~Donkey()" << endl;
    }

    void carry()
    {
        cout << "I can carry more!" << endl;
    }
};

class Mule: public Horse, public Donkey//构造函数调用顺序按从左到右调用
{
public:
    Mule()
    {
        cout << "Mule()" << endl;
    }

    // 只能由虚基类构造函数负责对从虚基类继承的所有属性进行初始化
    Mule(int id, int h, int d): Animal(id), Horse(8, h), Donkey(9, d)
    {
        cout << "Mule(int, int, int)" << endl;
    }

    ~Mule()
    {
        cout << "~Mule()" << endl;
    }

    void show()
    {
        cout << id << ' ' << h << ' ' << d << endl;
    }
};


int main()
{
    // Mule* m = new Mule;

    //m此时有两个 id, 显然不合理
    // m->Horse::id = 3;
    // m->Donkey::id = 5;
    // m->Animal::id = 9; 	//不能间接访问
    // m->id = 8;

    // cout << m->Donkey::id << endl;

    // m->Horse::eat();
    // m->Donkey::eat();
    // m->eat();

    // m->h = 5;
    // m->d = 6;
    // m->run();
    // m->carry();

    // delete m;

    Mule m(1, 2, 3);
    m.show();

    return 0;
}

实例二:对象类型转换

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


class Person
{
private:
    int id = 0;
    char name[20] = "";

public:
    Person()
    {
    }

    Person(int id, const char* name): id(id)
    {
        strcpy(this->name, name);
    }

    void setIdAndName(int id, const char* name)
    {
        this->id = id;
        strcpy(this->name, name);
    }

    virtual void show() const
    {
        cout << id << ' ' << name << endl;
    }
};


class Chinese: public Person
{
private:
    char shengXiao[8] = "";

public:
    Chinese()
    {
    }

    Chinese(int id, const char* name, const char* shengXiao): Person(id, name)
    {
        strcpy(this->shengXiao, shengXiao);
    }

    void guoNian()
    {
        cout << "新年快乐!" << endl;
    }

    void show() const
    {
        Person::show();
        cout << shengXiao << endl;
    }
};


class English: public Person
{
private:
    char queenName[20] = "";

public:
    English()
    {
    }

    English(int id, const char* name, const char* queenName): Person(id, name)
    {
        strcpy(this->queenName, queenName);
    }

    void christmas()
    {
        cout << "Happy Christmas!" << endl;
    }

    void show() const
    {
        Person::show();
        cout << queenName << endl;
    }
};


void showPerson(const Person& p);


int main()
{
    Person p1(1003, "lisi");  // 24
    English e1(1002, "Tom", "Alisa");  // 44
    Chinese c1(1001, "张三", "龙");     // 32

    Person* p2 = &c1;  // 向上转型,隐式进行
    p2->show();

    p2 = &e1;  // 向上转型,隐式进行
    p2->show();

    p2 = &p1;
    p2->show();

    // // 注意该函数的形参和实参类型
    // showPerson(p1);
    // showPerson(e1);
    // showPerson(c1);


    // p1 = c1;  // 向上转型,隐式进行
    // p1.show();
    // // e1 = (English)(p1);  

    // Person& p3 = c1;  // 向上转型,隐式进行
    // p3.show();

    // English* q = (English*)p;  // 向下转型,强制转型
    // q->show();

    // char c[4];
    // int* p;

    // p = (int*)&c;
    // *p = 65;

    // // Range based for statement
    // // 基于范围的 for 语句
    // for(char x : c)
    // {
    //     cout << (int)x << endl;
    // }

    // double* p = (double*)&c;
    // p = (double*)3;
    // *p = 3.14;


    return 0;
}


void showPerson(const Person& p)
{
    p.show();
}

实例三:虚函数

#include <iostream>
using namespace std;


class A
{
public:
    int a = 3;

    virtual void show()
    {
        cout << "A::show()" << endl;
    }
};

class B: public A
{
public:
    int a = 5;

    void show()
    {
        cout << "B::show()" << endl;
    }

    void show(int i)
    {
        cout << i << endl;
    }
};

class C: public A
{
public:
    void show()
    {
        cout << "C::show()" << endl;
    }
};


int main()
{
    B b;
    C c;

    A* p = &b;

    cout << p->a << endl;

    p->show();

    p = &c;

    p->show();

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值