• C++_抽象类


    C++_抽象类

    1、总结
    ①抽象类就是含有纯虚函数
    ②抽象类不能有实例对象
    ③子类没有覆写所有的纯虚函数,则子类还是抽象类

    #include 
    #include 
    #include 
    
    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; }
    	virtual Human* test(void) {cout<<"Human's test"<<endl; return this; }
    };
    
    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; }
    	virtual Englishman* test(void) {cout<<"Englishman's test"<<endl; return this; }
    };
    
    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; }
    	virtual Chinese* test(void) {cout<<"Chinese's test"<<endl; return this; }
    };
    
    int main(int argc, char **argv)
    {
    	//Human h;  //抽象类不能实例化对象
    	Englishman e;
    	Chinese c;
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    2、抽象类一步一步深入(利于提高代码利用率)代码分成多人协同开发,
    ①公用部分都放到基类里面,这样不用重复造轮子了,比如一下这个例子讲设置名字和或取名字的函数放在基类Human,不然每个类里面都要写这两个函数
    在这里插入图片描述

    Chinese.h

    #ifndef _CHINESE_H
    #define _CHINESE_H
    
    #include 
    #include 
    #include 
    
    #include "Human.h"
    
    using namespace std;
    
    class Chinese : public Human{
    public:
    	void eating(void);
    	void wearing(void);
    	void driving(void);
    	~Chinese();
    };
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    Chinese.cpp

    #include "Chinese.h"
    
    void Chinese::eating(void) 
    { 
    	cout<<"use chopsticks to eat"<<endl; 
    }
    
    void Chinese::wearing(void) 
    {
    	cout<<"wear chinese style"<<endl; 
    }
    
    void Chinese::driving(void) 
    {
    	cout<<"drive chinese car"<<endl; 
    }
    
    Chinese::~Chinese() 
    { 
    	cout<<"~Chinese()"<<endl; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    Englishman.h

    #ifndef _ENGLISHMAN_H
    #define _ENGLISHMAN_H
    
    #include 
    #include 
    #include 
    
    #include "Human.h"
    
    using namespace std;
    
    class Englishman : public Human {
    public:
    	void eating(void);
    	void wearing(void);
    	void driving(void);
    	~Englishman();
    };
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    Englishman.cpp

    #include "Englishman.h"
    
    void Englishman::eating(void) 
    { 
    	cout<<"use knife to eat"<<endl; 
    }
    
    void Englishman::wearing(void) 
    {
    	cout<<"wear english style"<<endl; 
    }
    
    void Englishman::driving(void) 
    {
    	cout<<"drive english car"<<endl; 
    }
    
    Englishman::~Englishman() 
    { 
    	cout<<"~Englishman()"<<endl; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    Human.h

    #ifndef _HUMAN_H
    #define _HUMAN_H
    
    #include 
    #include 
    #include 
    
    using namespace std;
    
    class Human {
    private:
    	char *name;
    
    public:
    	void setName(char *name);
    	char *getName(void);
    };
    
    #endif
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    Human.cpp

    #include "Human.h"
    
    void Human::setName(char *name) 
    {
    	this->name = name;
    }
    
    char *Human::getName(void) 
    {
    	return this->name;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    main.cpp

    #include "Englishman.h"
    #include "Chinese.h"
    
    int main(int argc, char **argv)
    {
    	Englishman e;
    	Chinese c;
    
    	e.setName("Bill");
    	c.setName("zhangsan");
    
        cout<< e.getName() <<endl; 
        cout<< c.getName() <<endl; 
    
    	e.eating();
    	c.eating();
    	
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    Makefile

    Human: main.o Chinese.o Englishman.o Human.o
    	g++ -o $@ $^
    
    %.o : %.cpp
    	g++ -c -o $@ $<
    
    clean:
    	rm -f *.o Human	
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3、程序分为:应用变成和类编程
    ①应用编程:实用类
    ②类编程:提供类,比如Englishman、Chinese
    ③在上个例子基础上,修改Makefile即可实现,就是把Englishman.o Chinese.o Human.o链接成libHuman.so动态库
    ④在执行可执行文件时候要指定去哪里找动态库(LD_LIBRARY_PATH=./ ./Human)
    ⑤这样做的好处就是修改了Englishman.cpp中的函数后不用重新编译生成应用层Human(只用make libHuman.so)

    Human: main.o libHuman.so
    	g++ -o $@ $< -L./ -lHuman
    
    %.o : %.cpp
    	g++ -fPIC -c -o $@ $<
    
    libHuman.so : Englishman.o Chinese.o Human.o
    	g++ -shared -o $@ $^
    
    clean:
    	rm -f *.o Human	
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4、下面承接3的例子,引出真正的抽象类界面
    ①3这个例子中为什么可以在Englishman.cpp文件修改后,只编译libHuman.so而不用重新编译Human就可以直接运行呢?,因为main.cpp中包含的是Englishman.h,没有包含Englishman.cpp,所以Englishman.cpp修改后没有影响程序的正常执行
    ②下面来复现①中提到的,修改Englishman.h后程序会不会崩溃
    ③实际情况是Englishman.h中的char address[100];改为char address[1000];后程序崩溃了,显然不符合我们之前所提出的类编程和应用编程应该相互独立的,下面就要想办法把main函数中的#include "Englishman.h"和#include "Chinese.h"给去掉,下面引出5实例

    Chinese.h

    #ifndef _CHINESE_H
    #define _CHINESE_H
    
    #include 
    #include 
    #include 
    
    #include "Human.h"
    
    using namespace std;
    
    class Chinese : public Human{
    public:
    	void eating(void);
    	void wearing(void);
    	void driving(void);
    	~Chinese();
    };
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    Chinese.cpp

    #include "Chinese.h"
    
    void Chinese::eating(void) 
    { 
    	cout<<"use chopsticks to eat"<<endl; 
    }
    
    void Chinese::wearing(void) 
    {
    	cout<<"wear chinese style"<<endl; 
    }
    
    void Chinese::driving(void) 
    {
    	cout<<"drive chinese car"<<endl; 
    }
    
    Chinese::~Chinese() 
    { 
    	cout<<"~Chinese()"<<endl; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    Englishman.h

    #ifndef _ENGLISHMAN_H
    #define _ENGLISHMAN_H
    
    #include 
    #include 
    #include 
    
    #include "Human.h"
    
    using namespace std;
    
    class Englishman : public Human {
    private:
    	char address[100];
    	int age;
    public:
    	void eating(void);
    	void wearing(void);
    	void driving(void);
    	Englishman();
    	Englishman(char *name, int age, char *address);
    	~Englishman();
    };
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    Englishman.cpp

    #include "Englishman.h"
    
    void Englishman::eating(void) 
    { 
    	cout<<"use knife to eat"<<endl; 
    }
    
    void Englishman::wearing(void) 
    {
    	cout<<"wear english style"<<endl; 
    }
    
    void Englishman::driving(void) 
    {
    	cout<<"drive english car"<<endl; 
    }
    
    Englishman::~Englishman() 
    { 
    	cout<<"~Englishman()"<<endl; 
    }
    
    Englishman::Englishman() {}
    Englishman::Englishman(char *name, int age, char *address)
    {
    	setName(name);
    	this->age = age;
    	memset(this->address, 0, 100);
    	strcpy(this->address, address);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    Human.h

    #ifndef _HUMAN_H
    #define _HUMAN_H
    
    #include 
    #include 
    #include 
    
    using namespace std;
    
    class Human {
    private:
    	char *name;
    
    public:
    	void setName(char *name);
    	char *getName(void);
    };
    
    #endif
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    Human.cpp

    #include "Human.h"
    
    void Human::setName(char *name) 
    {
    	this->name = name;
    }
    
    char *Human::getName(void) 
    {
    	return this->name;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    main.cpp

    #include "Human.h"
    #include "Englishman.h"
    #include "Chinese.h"
    
    void test_eating(Human *h)
    {
    	h->eating();
    }
    
    int main(int argc, char **argv)
    {
    	Englishman e("Bill", 10, "sfwqerfsdfas");
    	Chinese c;
    
    	Human* h[2] = {&e, &c};
    	int i;
    	for (i = 0; i < 2; i++)
    		test_eating(h[i]);
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    Makefile

    Human: main.o libHuman.so
    	g++ -o $@ $< -L./ -lHuman
    
    %.o : %.cpp
    	g++ -fPIC -c -o $@ $<
    
    libHuman.so : Englishman.o Chinese.o Human.o
    	g++ -shared -o $@ $^
    
    clean:
    	rm -f *.o Human	
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    5、把所有用到的东西都封装在Human.h中
    ①如一下这个程序结构
    在这里插入图片描述

    Chinese.h

    #ifndef _CHINESE_H
    #define _CHINESE_H
    
    #include 
    #include 
    #include 
    
    #include "Human.h"
    
    using namespace std;
    
    class Chinese : public Human{
    public:
    	void eating(void);
    	void wearing(void);
    	void driving(void);
    	virtual ~Chinese();
    };
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    Chinese.cpp

    #include "Chinese.h"
    
    
    void Chinese::eating(void) 
    { 
    	cout<<"use chopsticks to eat"<<endl; 
    }
    
    void Chinese::wearing(void) 
    {
    	cout<<"wear chinese style"<<endl; 
    }
    
    void Chinese::driving(void) 
    {
    	cout<<"drive chinese car"<<endl; 
    }
    
    Chinese::~Chinese() 
    { 
    	cout<<"~Chinese()"<<endl; 
    }
    
    Human& CreateChinese(char *name, int age, char *address)
    {
    	return *(new Chinese());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    Englishman.h

    #ifndef _ENGLISHMAN_H
    #define _ENGLISHMAN_H
    
    #include 
    #include 
    #include 
    
    #include "Human.h"
    
    using namespace std;
    
    class Englishman : public Human {
    private:
    	char address[100];
    	int age;
    public:
    	void eating(void);
    	void wearing(void);
    	void driving(void);
    	Englishman();
    	Englishman(char *name, int age, char *address);
    	virtual ~Englishman();
    };
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    Englishman.cpp

    #include "Englishman.h"
    
    void Englishman::eating(void) 
    { 
    	cout<<"use knife to eat"<<endl; 
    }
    
    void Englishman::wearing(void) 
    {
    	cout<<"wear english style"<<endl; 
    }
    
    void Englishman::driving(void) 
    {
    	cout<<"drive english car"<<endl; 
    }
    
    Englishman::~Englishman() 
    { 
    	cout<<"~Englishman()"<<endl; 
    }
    
    Englishman::Englishman() {}
    Englishman::Englishman(char *name, int age, char *address)
    {
    	setName(name);
    	this->age = age;
    	memset(this->address, 0, 100);
    	strcpy(this->address, address);
    }
    
    Human& CreateEnglishman(char *name, int age, char *address)
    {
    	return *(new Englishman(name, age, address));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    Human.h

    #ifndef _HUMAN_H
    #define _HUMAN_H
    
    #include 
    #include 
    #include 
    
    using namespace std;
    
    class Human {
    private:
    	char *name;
    
    public:
    	void setName(char *name);
    	char *getName(void);
    	virtual void eating(void) = 0;
    	virtual void wearing(void) = 0;
    	virtual void driving(void) = 0;
    	virtual ~Human() {cout<<"~Human"<<endl;}
    	
    };
    
    Human& CreateEnglishman(char *name, int age, char *address);
    Human& CreateChinese(char *name, int age, char *address);
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    Human.cpp

    #include "Human.h"
    
    void Human::setName(char *name) 
    {
    	this->name = name;
    }
    
    char *Human::getName(void) 
    {
    	return this->name;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    main.cpp

    #include "Human.h"
    //#include "Englishman.h"
    //#include "Chinese.h"
    
    void test_eating(Human *h)
    {
    	h->eating();
    }
    
    
    int main(int argc, char **argv)
    {
    	Human& e = CreateEnglishman("Bill", 10, "sfwqerfsdfas");
    	Human& c = CreateChinese("zhangsan", 11, "beijing");
    
    	Human* h[2] = {&e, &c};
    	int i;
    	for (i = 0; i < 2; i++)
    		test_eating(h[i]);
    
    	delete &e;
    	delete &c;
    	
    	
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    Makefile

    Human: main.o libHuman.so
    	g++ -o $@ $< -L./ -lHuman
    
    %.o : %.cpp
    	g++ -fPIC -c -o $@ $<
    
    libHuman.so : Englishman.o Chinese.o Human.o
    	g++ -shared -o $@ $^
    
    clean:
    	rm -f *.o Human	
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 相关阅读:
    极简实用PyTorch记录——如何读取图片、改变大小、转化为numpy数组、转化为tensor
    pytest测试框架pytest-html插件生成HTML格式测试报告
    危险的粒子 马蹄集
    SPA项目开发之表单验证&增删改功能
    计算机毕业设计选什么题目好?springboot 个人健康信息管理系统
    网络安全(黑客)自学笔记
    RocketMQ为什么要保证订阅关系一致
    【Linux】Make/Makefile
    求解 算法 二分归并排序
    git提交设置忽略指定文件,文件夹
  • 原文地址:https://blog.csdn.net/weixin_50183638/article/details/126501370