美文网首页C/C++Android/NDK开发C语言
(四)C++中的继承、多态和模板函数

(四)C++中的继承、多态和模板函数

作者: onestravel | 来源:发表于2019-04-02 10:54 被阅读6次

C++中的继承、多态和模板函数

一、继承

1、属性和方法的继承

继承可以更好的实现代码的重用性

#include <stdlib.h>
#include <iostream>

using namespace std;

//开发者
class Developer {
protected:
    char* language;
    char* ide;
    int age;
public:
    void say() {
        cout << "我是开发者" << endl;
    }
};

//Android开发者
class AndroidDeveloper : public Developer {
public:
    AndroidDeveloper() {
        this->language = (char*)"Android+Kotlin";
        this->ide = (char*)"Android Stuio";
    }
    //开发Android Application
    void createAndroidApp() {
        cout << "我使用" << this->ide << "开发了一款Android应用,使用了" << this->language << "语言" << endl;
    }
private:
    //Android 版本
    char* androidVersion;

};

//所有开发者都有开发工作
void work(Developer& d) {
    d.say();
}

void main() {
    AndroidDeveloper androidDev;
    androidDev.say();
    androidDev.createAndroidApp();
    //子类对象初始化父类类型的对象
    Developer d1 = androidDev;
    work(d1);
    //父类类型的指针
    Developer* d_p = &androidDev;
    d_p->say();
    //父类类型的引用
    Developer d2 = androidDev;
    d2.say();

    getchar();
}

2、通过子类给父类构造方法传参

父类的构造函数先调用;子类的析构函数先调用

//开发者
class Developer {
protected:
    char* language;
    char* ide;
    int age;
public:
    Developer(char * language, char* ide, int age) {
        this->language = language;
        this->ide = ide;
        this->age = age;
        cout << "Developer 构造函数" << endl;
    }
    ~Developer() {
        cout << "Developer 析构函数" << endl;
    }
    void say() {
        cout << "我是开发者" << endl;
    }
};

//Android开发者
class AndroidDeveloper : public Developer {
public:
    AndroidDeveloper(char* language, char* ide, int age, char* androidVersion) : Developer(language, ide, age) {
        this->language = language;
        this->ide = ide;
        this->age = age;
        cout << "AndroidDeveloper 构造函数" << endl;
    }
    ~AndroidDeveloper(){
        cout << "AndroidDeveloper 析构函数" << endl;
    }
    //开发Android Application
    void createAndroidApp() {
        cout << "我使用" << this->ide << "开发了一款Android应用,使用了" << this->language << "语言" << endl;
    }
private:
    //Android 版本
    char* androidVersion;

};

void work(Developer& d) {
    d.say();
}

//父类的构造函数先调用
//子类的析构函数先调用
void func() {
    AndroidDeveloper androidDev((char*)"Kotlin", (char*)"Android Studio", 5, (char*)"5.0.1");
    androidDev.say();
    androidDev.createAndroidApp();
}

void main() {
    func();
    getchar();
}

输出:

Developer 构造函数
AndroidDeveloper 构造函数
我是开发者
我使用Android Studio开发了一款Android应用,使用了Kotlin语言
AndroidDeveloper 析构函数
Developer 析构函数

3、继承中父类和子类的权限继承关系

基类中 继承方式 子类中
public & public继承 => public
public & protected继承 => protected
public & private继承 => private
protected & public继承 => protected
protected & protected继承 => protected
protected & private继承 => private
private & public继承 => 子类无权访问
private & protected继承 => 子类无权访问
private & private继承 => 子类无权访问

4、继承的二义性

4.1 继承的二义性定义

在某个类B同时继承另一个类A的两个或多个子类时(A1和A2),通过类B访问类A的成员时,会出现成员不明确的情况,即继承的二义性

class A {
public:
    char* name;
};

class A1 : public A {

};

class A2 : public A {

};

class B : public A1, public A2 {

};

void main() {
    B b;
    //报错,提示B::name不明确
    //b.name = (char*)"Jack";

    //指定父类显式调用
    b.A1::name = (char*)"Rose";
    getchar();
}

4.2 继承的二义性定义解决方案

再遇到继承的二义性时,可使用虚继承来解决继承的二义性问题
虚继承:不同路径继承来的同名成员只有一份拷贝

class A {
public:
    char* name;
};

class A1 : virtual public A {

};

class A2 : virtual public A {

};

class B : public A1, public A2 {

};

void main() {
    B b;
    //报错,提示B::name不明确
    //b.name = (char*)"Jack";

    //指定父类显式调用
    b.A1::name = (char*)"Rose";
    getchar();
}

二、多态

  • 多态是为了提高程序的扩展性
  • 动态多态:子类重写父类的函数,程序运行过程中,决定哪一个函数被调用
  • 静态多态:就是函数重载

1、虚函数

virtual 关键字修饰的函数叫虚函数,用来实现多态

例如:

Plane.h

#pragma once

class Plane {
public:
    virtual void fly();
    virtual void land();
};

Plane.cpp

#include "Plane.h"
#include <stdlib.h>
#include <iostream>

using namespace std;
void Plane::fly() {
    cout << "飞机起飞" << endl;
}

void Plane::land() {
    cout << "飞机降落" << endl;
}

Helicopter.h

#pragma once
#include "Plane.h"

class Helicopter : public Plane {
public:
    virtual void fly();
    virtual void land();
};

Helicopter.cpp

#include "Helicopter.h"
#include <stdlib.h>
#include <iostream>

using namespace std;
void Helicopter::fly() {
    cout << "直升飞机在原地起飞" << endl;
}

void Helicopter::land() {
    cout << "直升飞机降落在屋顶" << endl;
}

Test.cpp

#include <stdlib.h>
#include <iostream>
#include "Plane.h"
#include "Helicopter.h"
using namespace std;

//业务函数

void runPlane(Plane &p) {
    p.fly();
    p.land();
}

void main() {
    Plane p;
    
    runPlane(p);
    Helicopter h;
    //在 Plane.h 和 Helicopter.h 中的函数上不使用 virtual 修饰时,打印“飞机起飞”和“飞机降落”
    //使用 virtual 修饰时,打印“直升飞机在原地起飞”和“直升飞机降落在屋顶”,实现多态
    runPlane(h);
    getchar();
}

2、发生动态多态的条件

  • 使用继承
  • 父类的引用或指针指向子类的对象
  • 函数的重写

3、纯虚函数(抽象类)

  • 当一个类具有一个纯虚函数时,这个类就是抽象类
  • 抽象类不能被实例化
  • 子类继承抽象类,必须要实现纯虚函数,如果没有重新,子类也是抽象类
//形状
class Shape {
public:
    virtual void sayArea() = 0;
};

//圆
class Circle : public Shape {
private:
    int r;
public:
    Circle(int r) {
        this->r = r;
    }
    void sayArea() {
        cout << "圆的面积:" << 3.14 * r * r << endl;
    }
};

void main() {
    Circle c(5);
    c.sayArea();
    getchar();
}

4、接口

接口只是逻辑上的划分,语法上跟抽象类的写法没有区别

//可以看作一个接口
class Drawable{
    virtual void draw() = 0;
}

5、抽象类的作用

为了继承约束,子类必须按照约束实现

//可以看作一个接口
class Drawable{
    virtual void draw() = 0;
}

二、模板函数(泛型)

函数模板类似于泛型,用于在业务相同,参数类型不同时进行声明,在使用过程中,根据实际类型进行推导

template <typename T,typename Z>
//交换两个变量的值
void swap(T& a, Z& b){
    T tmp = 0;
    tmp = a;
    a = b;
    b = tmp;
}

void main(){
    int a = 10;
    int b = 25;
    swap(a,b);
    cout << a << "," << b << endl;
    
    char* x = (char*)"abc";
    char* y = (char*)"def";
    swap(x,y);
    cout << x << "," << y << endl;
    
    getchar();
}

相关文章

  • (四)C++中的继承、多态和模板函数

    C++中的继承、多态和模板函数 一、继承 1、属性和方法的继承 继承可以更好的实现代码的重用性 2、通过子类给父类...

  • 深刻剖析之c++博客文章

    三大特性 封装、继承、多态 多态 C++ 虚函数表解析C++多态的实现原理 介绍了类的多态(虚函数和动态/迟绑定)...

  • C++第六篇多态

    C++中的多态性分为编译时多态性和运行时多态性,编译时多态通过函数重载和模板体现,运行多态通过虚函数体现编译、连接...

  • 2020-07-06----《C++类的学习》

    函数重载:同名不同参。 C++类的特点:封装、继承、多态。 //多态与函数重载是啥关系? 虚函数:和软件架构相关 ...

  • C++知识点(自用)

    关于struct和class c++中的struct可以有成员函数,能继承,能实现多态。。。那struct和cla...

  • 深入研究C++多态(虚函数和虚继承)

    面向对象的三大特性是封装、继承和多态。多态是非常重要的一个特性,C++多态基于虚函数和虚继承实现,本文将完整挖掘C...

  • 02汇编角度理解虚函数的实现

    面向对象语言的三大特性 封装继承和多态。c++ 中的多态是通过虚函数实现的。我们声明一个Person类,然后 编写...

  • 技能

    C++ C++特性 C++11 多态和继承 构造函数 析构函数 手写代码实现string类 手写代码实现智能指针 ...

  • C++语言-多态,纯虚函数,模版函数

    1、虚函数、纯虚函数 需要注意的是,纯虚函数子类是必须继承的,虚函数不是不必须继承的。 2、多态 在C++中默认关...

  • 虚继承和虚函数

    虚继承和虚函数 虚继承和虚函数是毫不相关的两个概念,但是在实现上又有所类似;虚函数是C++中实现多态的一个重要手段...

网友评论

    本文标题:(四)C++中的继承、多态和模板函数

    本文链接:https://www.haomeiwen.com/subject/plvrvqtx.html