C++_抽象类

C++_抽象类

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

#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; }
	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;
}

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

Chinese.h

#ifndef _CHINESE_H
#define _CHINESE_H

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

#include "Human.h"

using namespace std;

class Chinese : public Human{
public:
	void eating(void);
	void wearing(void);
	void driving(void);
	~Chinese();
};

#endif

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; 
}

Englishman.h

#ifndef _ENGLISHMAN_H
#define _ENGLISHMAN_H

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

#include "Human.h"

using namespace std;

class Englishman : public Human {
public:
	void eating(void);
	void wearing(void);
	void driving(void);
	~Englishman();
};

#endif

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; 
}

Human.h

#ifndef _HUMAN_H
#define _HUMAN_H

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

using namespace std;

class Human {
private:
	char *name;

public:
	void setName(char *name);
	char *getName(void);
};

#endif
#endif

Human.cpp

#include "Human.h"

void Human::setName(char *name) 
{
	this->name = name;
}

char *Human::getName(void) 
{
	return this->name;
}

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;
}

Makefile

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

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

clean:
	rm -f *.o Human	

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	

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 <iostream>
#include <string.h>
#include <unistd.h>

#include "Human.h"

using namespace std;

class Chinese : public Human{
public:
	void eating(void);
	void wearing(void);
	void driving(void);
	~Chinese();
};

#endif

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; 
}

Englishman.h

#ifndef _ENGLISHMAN_H
#define _ENGLISHMAN_H

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

#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

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.h

#ifndef _HUMAN_H
#define _HUMAN_H

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

using namespace std;

class Human {
private:
	char *name;

public:
	void setName(char *name);
	char *getName(void);
};

#endif
#endif

Human.cpp

#include "Human.h"

void Human::setName(char *name) 
{
	this->name = name;
}

char *Human::getName(void) 
{
	return this->name;
}

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;
}

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	

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

Chinese.h

#ifndef _CHINESE_H
#define _CHINESE_H

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

#include "Human.h"

using namespace std;

class Chinese : public Human{
public:
	void eating(void);
	void wearing(void);
	void driving(void);
	virtual ~Chinese();
};

#endif

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());
}

Englishman.h

#ifndef _ENGLISHMAN_H
#define _ENGLISHMAN_H

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

#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

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));
}

Human.h

#ifndef _HUMAN_H
#define _HUMAN_H

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

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

Human.cpp

#include "Human.h"

void Human::setName(char *name) 
{
	this->name = name;
}

char *Human::getName(void) 
{
	return this->name;
}

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;
}

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	
  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值