C++:抽象类

1. 概念

抽象类的定义:函数前面为 vritual 并且函数体为 “=0” 的函数称为纯虚函数。含纯虚函数的类称为抽象类

抽象类的作用:向下(给派生类)定义好框架,向上(应用程序)提供统一的接口

抽象类要注意的点:
1)抽象类不能够用来实例化对象。例如:实例化一个人时可以是"英国人",“中国人”,而不是"人类"。
2)如果派生类没有实现完父类所有的纯虚函数,那么派生类依然是抽象类,要么将剩下的纯虚函数实现,要么进一步派生子类在子类中实现。

#include <iostream>
#include <string.h>
#include <unistd.h>

using namespace std;

class Human {
private:
    int a;
public:
    virtual void eating(void) = 0;
    virtual void wearing(void) = 0;
    virtual void driving(void) = 0;
    virtual ~Human() { cout<<"~Human()"<<endl; }
};

class Englishman : public Human {
public:
    void eating(void) { cout<<"use knife to eat"<<endl; }
    void wearing(void) {cout<<"wear english style"<<endl; }
    void driving(void) {cout<<"drive english car"<<endl; }
    virtual ~Englishman() { cout<<"~Englishman()"<<endl; }
};

class Chinese : public Human {
public:
    void eating(void) { cout<<"use chopsticks to eat"<<endl; }
    void wearing(void) {cout<<"wear chinese style"<<endl; }
    //void driving(void) {cout<<"drive chinese car"<<endl; }
    virtual ~Chinese() { cout<<"~Chinese()"<<endl; }
};

class Guangximan : public Chinese {
    void driving(void) {cout<<"drive guangxi car"<<endl; }
};

int main(int argc, char **argv)
{
    //Human h;
    Englishman e;
    Guangximan g;
    
    return 0;
}

2. 实战

02th:规范化组织和书写cpp代码的规则:

  • h文件中定义类,cpp文件包含h文件,并实现类方法;
  • 使用#ifdef 宏避免头文件被重复包含。

03th:抽象出共有属性放到基类中,子类继承基类,减少重复代码;

04th:基类引入虚函数实现多态–相同调用方法会根据不同对象调用对象所属类里面的函数。

05th:基类引入纯虚函数实现抽象类;好处是:

  • 1)基类节省不必要的代码(往往并不需要基类实现虚函数的内容,只需要提供接口即可);
  • 2)阻值生成基类的实例化对象

06th:编程工程化分工协作
将由一个人进行的工作拆分为分工协作:

  • 1)应用编程:使用类;
  • 2)类编程:提供类,比如Englishman, Chinese

第一步:修改Makefile,将类和应用程序分开。这样类更新(类的cpp文件)后不需要重新编译生成应用程序。

Human: main.o Chinese.o Englishman.o Human.o
    g++ -o $@ $^

%.o : %.cpp
    g++ -c -o $@ $<

改为:

Human: main.o libHuman.so
    # -L./ 指定编译时动态库的路径,-l 指定链接的动态库的名字(libXXX.so中的XXX)
    g++ -o $@ $< -L./ -lHuman 

%.o : %.cpp
    # -fPIC:编译选项 -- 编译为位置无关码
    g++ -fPIC -c -o $@ $< 

libHuman.so : Englishman.o Chinese.o Human.o
    # -shared:连接选项 -- 链接为动态库
    g++ -shared -o $@ $^

执行时用 LD_LIBRARY_PATH 指定链接路径:

LD_LIBRARY_PATH=<dir> ./Human

07th:抽象类界面的引入
06th的代码存在的问题:由于应用程序包含了类的头文件,如果类的头文件有修改,那么应用程序需要重新编译。
解决办法:应用程序应尽量包含内容比较固定的头文件,而不要去包含可能会经常变化的头文件。这就是抽象类界面机制。

             app 
---------------------------------
			# 相对固定的接口(声明)
             Human.h 
---------------------------------
Englishman                Chinese

08th:抽象类界面的实现


#应用编程:包含固定的引用接口头文件 Human.h,调用接口
             app 
---------------------------------
			# 相对固定的接口(声明)
             Human.h
---------------------------------
#类编程:包含固定的接口头文件 Human.h,实现方法
Englishman                Chinese

这样,类编程就完全和应用独立开了。

09th:完善:基类和子类的析构函数都实现为虚函数,以在delete对象时实现多态。

注意,基类析构函数不能为纯虚函数,这样子类就要实现与基类同名的析构函数,这很怪异。

©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页