纯虚函数和抽象类
纯虚函数和抽象类
定义
注意抽象类不能创建对象,但是可以定义一个指针
注意抽象类不能有任何成员结构, 成员函数必须协成纯虚函数,
virtual 返回值 函数名(参数列表)=0
注意
含有纯虚函数的类被称为抽象类。抽象类只能作为派生类的基类,不能定义对象,但可以定义指针。在派生类实现该纯虚函数后,定义抽象类对象的指针,并指向或引用子类对象。
1)在定义纯虚函数时,不能定义虚函数的实现部分;
2)在没有重新定义这种纯虚函数之前,是不能调用这种函数的。
抽象类的唯一用途是为派生类提供基类,纯虚函数的作用是作为派生类中的成员函数的基础,并实现动态多态性。继承于抽象类的派生类如果不能实现基类中所有的纯虚函数,那么这个派生类也就成了抽象类。因为它继承了基类的抽象函数,只要含有纯虚函数的类就是抽象类。纯虚函数已经在抽象类中定义了这个方法的声明,其它类中只能按照这个接口去实现。
抽象类实例
计算图形面积
#include <iostream> using namespace std; // 重点 // 面向抽象类编程(面向一套预先定义好的接口编程) // 解耦合。。模块的划分 class Figure // 抽象类 { public: // 约定一个统一的界面(接口) 让子类使用,让子类必须去实现 virtual void getArea() = 0; // 纯虚函数 protected: private: }; class Circle : public Figure { public: Circle(int a, int b) { this->a = a; this->b = b; } virtual void getArea() { cout << "圆的面积\t" << 3.14 * a * a << endl; } protected: private: int a; int b; }; class Sanjiao : public Figure { public: Sanjiao(int a, int b) { this->a = a; this->b = b; } virtual void getArea() { cout << "三角形的面积\t" << a * b / 2 << endl; } protected: private: int a; int b; }; class Squre : public Figure { public: Squre(int a, int b) { this->a = a; this->b = b; } virtual void getArea() { cout << "四边形的面积\t" << a * b << endl; } protected: private: int a; int b; }; void PlayObj(Figure *base) { base->getArea(); // 会发生多态 } int main() { // Figure f1; // 抽象类不能被实例化 Figure *base = NULL; Circle c1(1, 2); Squre sq(1, 2); Sanjiao s1(2, 4); PlayObj(&c1); PlayObj(&s1); PlayObj(&sq); return 0; }
计算程序员工资
忘记了手动调用delete,让其调用析构函数比较好
第二个有点错误, 不能说是抽象类
#include <iostream> using namespace std; /* 编写一个c++程序 计算程序员工资(programer) 1要求:能计算出初级程序员工资(junior_programer),中级程序员(mid_programer),高级程序员(Adv_progreamer) 2要求利用抽象类统一界面(方便程序拓展),比如新增 计算架构师architect的工资 */ // 程序员抽象类 class programer { public: virtual void getSal() = 0; // 抽象类接口 }; // 初级程序员 class junior_programer: public programer { public: junior_programer(char *name, char *job, int sal) // 浅拷贝 { this->name = name; this->job = job; this->sal = sal; } virtual void getSal() // 接口类实现 { cout << "name = " << name << "\tjob = " << job << "\tsal = " << sal << endl; } private: char *name; char *job; int sal; }; // 中级程序员 class mid_programer: public programer { public: mid_programer(char *name, char *job, int sal) // 浅拷贝 { this->name = name; this->job = job; this->sal = sal; } virtual void getSal() // 接口类实现 { cout << "name = " << name << "\tjob = " << job << "\tsal = " << sal << endl; } private: char *name; char *job; int sal; }; // 高级程序员 class Adv_programer: public programer { public: Adv_programer(char *name, char *job, int sal) // 浅拷贝 { this->name = name; this->job = job; this->sal = sal; } virtual void getSal() // 接口类实现 { cout << "name = " << name << "\tjob = " << job << "\tsal = " << sal << endl; } private: char *name; char *job; int sal; }; // 后来增加的 架构师类 class architect: public programer { public: architect(char *name, char *job, int sal) // 浅拷贝 { this->name = name; this->job = job; this->sal = sal; } virtual void getSal() // 接口类实现 { cout << "name = " << name << "\tjob = " << job << "\tsal = " << sal << endl; } private: char *name; char *job; int sal; }; // 计算函数,简单框架 void jisuan(programer *base) { base->getSal(); } // 引用 void jisuan(programer &base) { base.getSal(); } int main() { junior_programer junior("张三", "初级", 5000); mid_programer mid("李四", "中级", 10000); Adv_programer adv("王五", "高级", 15000); // 系统扩展 增加代码 架构师工资 architect arc("康总", "架构师", 30000); jisuan(&junior); jisuan(&mid); jisuan(&adv); jisuan(&arc); cout << endl; // 引用类型 auto &i = junior; auto &j = mid; auto &k = adv; auto &l = arc; jisuan(i); jisuan(j); jisuan(k); jisuan(l); return 0; }
//编写一个c++程序 计算程序员工资(programer) //1要求:能计算出初级程序员工资(junior_programer),中级程序员(mid_programer),高级程序员(Adv_progreamer) //2要求利用抽象类统一界面(方便程序拓展),比如新增 计算架构师architect的工资 #include <iostream> #include <cstring> using namespace std; // 定义程序员类, 抽象类 class Programer { virtual double getSal() = 0; }; class Junior : Programer { public: Junior(char *name = NULL, char *job = NULL, double sal = 7000) { auto len = strlen(name); this->name = new char[len + 1]; strcpy(this->name, name); len = strlen(job); this->job = new char[len + 1]; strcpy(this->job, job); this->sal = sal; } virtual ~Junior() { delete[]name; delete[]job; sal = 0; name = NULL; job = NULL; cout << "j" << endl; } virtual double getSal() { cout << this->name << " : " << this->job << ": " << this->sal << endl; } public: char *name; char *job; double sal; }; class Mid : public Junior { public: Mid(char *name = NULL, char *job = NULL, double sal = 10000) : Junior(name, job, sal) { } virtual ~Mid() // 会默认调用父类的析构函数 { cout << "m" << endl; } }; // 高级的 class Adv : public Junior { public: Adv(char *name = NULL, char *job = NULL, double sal = 10000) : Junior(name, job, sal) { } virtual ~Adv() // 会默认调用父类的析构函数 { cout << "Adv" << endl; } }; void print(Junior &obj) { obj.getSal(); } int main() { Junior j("张三", "初级", 5000); Mid m("李四", "中级", 10000); Adv a("王五", "高级", 15000); print(j); print(m); print(a); return 0; }
抽象类编程
动物园类
#if 0 // main.cpp #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include "Animal.h" #include "Dog.h" #include "Cat.h" #include "Dog.cpp" #include "Cat.cpp" #include "Animal.cpp" using namespace std; int main(void) { letAnimalCry(new Dog); letAnimalCry(new Cat); #if 0 Animal *dog = new Dog; letAnimalCry(dog); delete Dog; #endif return 0; } #endif // -- Animal.h #if 0 #pragma once #define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; class Animal { public: //纯虚函数,让子类继承并且实现 virtual void voice() = 0; Animal(); virtual ~Animal(); }; //架构函数 //让动物叫 void letAnimalCry(Animal *animal); #endif // Animal.cpp #if 0 #include "Animal.h" inline Animal::Animal() { cout << "animal().." << endl; } inline Animal::~Animal() { cout << "~Animal()..." << endl; } inline void letAnimalCry(Animal *animal) { animal->voice(); // 需要手动调用delete 让其调用析构函数 if (animal != NULL) { delete animal; } } #endif // Dog.h------------------------ #if 0 #pragma once #include "Animal.h" class Dog : public Animal { public: Dog(); ~Dog(); virtual void voice(); }; #endif // Dog.cpp #if 0 #include "Dog.h" inline Dog::Dog() { cout << "Dog().." << endl; } inline Dog::~Dog() { cout << "~Dog().." << endl; } inline void Dog::voice() { cout << "狗开始哭了, 555" << endl; } #endif // Cat.h #if 0 #pragma once #include "Animal.h" class Cat : public Animal { public: Cat(); ~Cat(); virtual void voice(); }; #endif // Cat.cpp #if 0 #include "Cat.h" inline Cat::Cat() { cout << "cat().." << endl; } inline Cat::~Cat() { cout << "~cat().." << endl; } inline void Cat::voice() { cout << "小猫开始哭了,66666" << endl; } #endif
电脑类实例:
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; //-------- 抽象层--------- //抽象CPU类 class CPU { public: // CPU(); virtual void caculate() = 0; }; //抽象的card类 class Card { public: virtual void display() = 0; }; //抽象的内存类 class Memory { public: virtual void storage() = 0; }; //架构类 class Computer { public: Computer(CPU *cpu, Card *card, Memory *mem) { this->cpu = cpu; this->card = card; this->mem = mem; } void work() { this->cpu->caculate(); this->card->display(); this->mem->storage(); } ~Computer() { if (this->cpu != NULL) { cout << "~cpu" << endl; delete this->cpu; } if (this->card != NULL) { cout << "~card"<<endl; delete this->card; } if (this->mem != NULL) { cout << "~mem"<<endl; delete this->mem; } } private: CPU *cpu; Card *card; Memory *mem; }; // -------------------------- //-----------实现层---------- //具体的IntelCPU class IntelCPU : public CPU { public: virtual void caculate() { cout << "Intel CPU开始计算了" << endl; } }; class IntelCard : public Card { public: virtual void display() { cout << "Intel Card开始显示了" << endl; } }; class IntelMem : public Memory { public: virtual void storage() { cout << "Intel mem开始存储了" << endl; } }; class NvidiaCard : public Card { public: virtual void display() { cout << "Nvidia 显卡开始显示了" << endl; } }; class KingstonMem : public Memory { public: virtual void storage() { cout << "KingstonMem 开始存储了" << endl; } }; //-------------------------- void test() { Computer *com1 = new Computer(new IntelCPU, new IntelCard, new IntelMem); com1->work(); delete com1; // 如果定义一个指针不要忘记释放 } //--------业务层------------------- int main() { //1 组装第一台intel系列的电脑 #if 0 CPU *intelCpu = new IntelCPU; Card *intelCard = new IntelCard; Memory *intelMem = new IntelMem; Computer *com1 = new Computer(intelCpu, intelCard, intelMem); com1->work(); Card *nCard = new NvidiaCard; Memory* kMem = new KingstonMem; Computer *com2 = new Computer(intelCpu, nCard, kMem); com2->work(); delete intelCpu; #endif // Computer *com1 = new Computer(new IntelCPU, new IntelCard, new IntelMem); // com1->work(); // delete com1; // 这里不要忘记释放 test(); return 0; }
圆类
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; //抽象的图形类 class Shape { public: //打印出图形的基本你属性 virtual void show() = 0; //得到图形的面积 virtual double getArea() = 0; virtual ~Shape() { } }; //圆类 class Circle :public Shape { public: Circle(double r) { this->r = r; } //打印出图形的基本你属性 virtual void show() { cout << "圆的半径是 " << r << endl; } //得到图形的面积 virtual double getArea() { cout << "获取圆的面积" << endl; return this->r*this->r *3.14; } ~Circle() { cout << "圆的析构函数。。" << endl; } private: double r; }; class Square :public Shape { public: Square(double a) { this->a = a; } //打印出图形的基本你属性 virtual void show() { cout << "正方形的边长是" << this->a << endl; } //得到图形的面积 virtual double getArea() { cout << "得到正方形的面积" << endl; return a*a; } ~Square() { cout << "正方形的析构函数" << endl; } private: double a; }; int main(void) { Shape *array[2] = { 0 }; for (int i = 0; i < 2; i++) { //生成一个圆 if (i == 0) { double r; cout << "请输入圆的半径" << endl; cin >> r; array[i] = new Circle(r); } //生成一个正方形 else { double a; cout << "请输入正方形的边长" << endl; cin >> a; array[i] = new Square(a); } } //遍历这个array数组 for (int i = 0; i < 2; i++) { array[i]->show(); cout << array[i]->getArea() << endl; delete array[i]; } return 0; }
比较大的例子,推荐看看
多态练习, 企业信息管理
https://i.cnblogs.com/Files.aspx
函数指针与多态
函数指针基础
#include <cstdio> #include <cstdlib> #include <cstring> // 数组类型, 基本语法知识梳理 // 定义一个数组类型 // int arr[10]; // 定义一个指针数组类型 // 定义一个指向 数组类型的指针, 数组类的指针 int main() { int a[10]; // a代表数组首元素地址, &a 代表整个数组的地址 // a+1 代表步长加4个单元,就是a[1]的地址, // &a+1 代表步长加40个单元后的地址 // { // 定义数组类型 typedef int (myTypeArr)[10]; myTypeArr myArr; myArr[0] = 10; printf("%d\n", myArr[0]); } { // 定义一个指针数组类型 typedef int (*PTypeArray)[10]; // int * p PTypeArray myPArray; // sizeof(int) * 10; 步长, myPArray 是一个二级指针 myPArray = &a; // 相当于 // int b = 10; // int *c = NULL; // c = &b; (*myPArray)[0] = 20; // 注意这里 printf("%d\n", a[0]); } { // 定义一个指向 数组类型的指针, 数组类的指针 int (*MyPoint)[10]; // 告诉c编译器给我分配内存 MyPoint = &a; (*MyPoint)[0] = 40; printf("%d\n", a[0]); } return 0; } // 函数指针语法知识梳理 // 如何定义一个函数类型 // 如何定义一个函数指针类型 // 如何定义一个函数指针(指向一个函数入口地址) int add(int a, int b) { printf("func add...\n"); return a + b; } int main01() { add(1, 2); // 直接调用// 函数名就是函数入口地址 // 如何定义一个函数类型 { typedef int (myFuncType)(int a, int b); // 定义一个类型 myFuncType *myFuncTypePoint = NULL; // 定义了一个指针,指向某一种类的函数 myFuncTypePoint = &add; // 细节,这里的&add &可以不加 myFuncTypePoint(1, 2); // 间接调用 } // 定义一个函数指针类型 { typedef int (*MyPointFuncType)(int a, int b); // int *a = NULL; MyPointFuncType myPointFunc = NULL; // 定义一个指针 myPointFunc = add; myPointFunc(1, 2); } // 函数指针 { int (*myPointFunc)(int a, int b); // 定义一个变量 myPointFunc = add; myPointFunc(1, 2); } }
#include <stdio.h> #include <stdlib.h> #include <string.h> int myAdd(int a, int b) { printf("func myAdd...\n"); return a + b; } int myAdd2(int a, int b) // 相当于虚函数表 { printf("func myAdd2...\n"); return a + b; } // 定义了一个类型 typedef int (*myTypeFuncAdd)(int a, int b); // mainop都是函数指针做函数参数 int mainop(myTypeFuncAdd myFuncAdd) { int c = myFuncAdd(1, 2); // 间接调用 printf("mainop\n"); return c; } // int (*myTypeFuncAdd)(int a, int b); 定义一个指向某种函数的指针 int mainop2(int (*myTypeFuncAdd)(int a, int b)) { int c = myTypeFuncAdd(1, 2); // 间接调用 printf("mainop2\n"); return c; } // 间接调用 // 任务的调用,和任务的编写可以分开 int main() { /* myTypeFuncAdd myfuncAdd = myAdd; myfuncAdd(1, 3); // 直接调用 mainop(myAdd); mainop2(myAdd); */ mainop(myAdd); mainop(myAdd2); // 相当于发生了多态,函数指针做函数参数 return 0; }
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; int func(int a, int b) { cout << " 1999 年写的 func" << endl; return 0; } int func2(int a, int b) { cout << "1999 写的 func2" << endl; return 0; } int func3(int a, int b) { cout << "1999年 写的 func3 " << endl; return 0; } //2018想添加一个新的子业务 int new_func4(int a, int b) { cout << "2018 新写的子业务" << endl; cout << "a = " << a << ", b = " << b << endl; return 0; } //方法一: 函数的返回值, 函数的参数列表(形参的个数,类型,顺序) //定义一个函数类型。 typedef int(FUNC)(int, int); //方法二: 定义一个函数指针 typedef int(*FUNC_P)(int, int); //定义一个统一的接口 将他们全部调用起来。 void my_funtion(int(*fp)(int, int), int a, int b) { cout << "1999年实现这个架构业务" << endl; cout << "固定业务1" << endl; cout << "固定业务2" << endl; fp(a, b);//可变的业务 cout << "固定业务3" << endl; } int main(void) { #if 0 //方法一: FUNC *fp = NULL; fp = func; fp(10, 20); FUNC_P fp2 = NULL; fp2 = func; fp2(100, 200); //方法三: int(*fp3)(int, int) = NULL; fp3 = func; fp3(1000, 3000); #endif my_funtion(func, 10, 20); my_funtion(func2, 100, 200); my_funtion(func3, 1000, 2000); my_funtion(new_func4, 2000, 3000); return 0; }
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; //-------------抽象层------------ //定义拆开锦囊方法的类型。 typedef void(TIPS)(void); //定义锦囊 struct tip { char from[64]; //谁写的 char to[64];//写给谁的。 //锦囊的内容 TIPS *tp;//相当于抽象类的 纯虚函数. }; //需要一个打开锦囊的架构函数 void open_tips(struct tip *tip_p) { cout << "打开了锦囊" << endl; cout << "此锦囊是由" << tip_p->from << "写给 " << tip_p->to << "的。" << endl; cout << "内容是" << endl; tip_p->tp(); //此时就发生了多态现象。 } //提供一个创建一个锦囊的方法 struct tip* create_tip(char*from, char *to, TIPS*tp) { struct tip *temp = (struct tip*)malloc(sizeof(struct tip)); if (temp == NULL) { return NULL; } strcpy(temp->from, from); strcpy(temp->to, to); //给一个回调函数赋值, 一般称 注册回调函数 temp->tp = tp; return temp; } //提供一个销毁锦囊的方法 void destory_tip(struct tip *tp) { if (tp != NULL) { free(tp); tp = NULL; } } // ------------- 实现层------------ //诸葛亮写了3个锦囊 void tip1_func(void) { cout << "一到东吴就拜会乔国老" << endl; } void tip2_func(void) { cout << "如果主公乐不思蜀,就谎称曹贼来袭。赶紧回来 " << endl; } void tip3_func(void) { cout << "如果被孙权追杀,向孙尚香求救" << endl; } void tip4_func(void) { cout << "如果求救孙尚香都不灵, 你们去死了, 我是蜀国老大了" << endl; } //--------------- 业务层----------------- int main(void) { //创建出3个锦囊 struct tip *tip1 = create_tip("孔明", "赵云", tip1_func); struct tip *tip2 = create_tip("孔明", "赵云", tip2_func); struct tip *tip3 = create_tip("孔明", "赵云", tip3_func); struct tip *tip4 = create_tip("庞统", "赵云", tip4_func); //由赵云进行拆锦囊。 cout << "刚刚来到东吴, 赵云打开第一个锦囊" << endl; open_tips(tip1); cout << "-----------" << endl; cout << "刘备乐不思蜀, 赵云打开第二个锦囊" << endl; open_tips(tip2); cout << "-----------" << endl; cout << "孙权大军追杀,赵云打开第三个锦囊" << endl; open_tips(tip3); cout << "-----------" << endl; cout << "赵云发现,实在是杀不动了, 打开了第四个锦囊" << endl; open_tips(tip4); destory_tip(tip1); destory_tip(tip2); destory_tip(tip3); destory_tip(tip4); return 0; }
未完待续....