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