C++学习之路 day8
来源:互联网 发布:数据库集群 编辑:程序博客网 时间:2024/05/16 08:15
Day8 知识点:
1.赋值兼容
赋值兼容只能发生在公有派生继承的父子关系中。
a) 子类对象(派生类)赋给父类(基类)的对象
b) 子类对象赋给父类的引用
c) 子类对象的地址赋给父类的指针
实验代码:
#include <iostream>using namespace std;class shape{public: shape(int x = 0, int y = 0) :_x(x),_y(y){} void draw() { cout<<"drawfrom"<<"("<<_x<<","<<_y<<")"<<endl; }protected: int _x; int _y;};class circle:public shape{public: circle(int x = 0, int y = 0, int r = 0) :shape(x,y),_radius(r){} void draw() { cout<<"drawfrom"<<"("<<_x<<","<<_y<<")"; cout<<" radius = "<<_radius<<endl; } void func() { cout<<"------------------"<<endl; }private: int _radius;};int main(){ shape s(1,2); s.draw(); circle c(1,2,3); c.draw(); c.func(); shape s1 = c; //派生类对象赋给基类对象 s1.draw(); shape &rc = c; //派生类对象赋给基类的引用 rc.draw(); shape *pc = &c; //派生类对象的地址赋给指向基类的指针 pc->draw(); return 0;}
2.多态:由继承产生的相关的不同的类,对同一消息做出的不同响应。
静多态,编译阶段决定的
#include <iostream>using namespace std;void func(int a, float b){ cout<<"void func(int a, float b)"<<endl;}void func(float a, int b){ cout<<"void func(float a, int b)"<<endl;}int main(){ func(1,3.0); //在编译阶段就完成函数的倾轧 func(3.0,1); return 0;}
动多态,运行阶段决定的
实现条件:
1)父类中有虚函数(在函数声明前加virtual,定义时不需要)
2)子类中覆写(override)了父的虚函数,根据需要重新定义函数体
{
a)overload重载 同一作用域中,函数名相同,参数列表不同;
b)shadow 发生在父子类中的同名成员(函数或数据,如果是函数只要同名就会构成shadow);
c)override 发生在父子类中,父类中函数有virtual声明的函数,子类中同参,同名,同返回。
}
3)成员函数被声明为虚函数后,其子类中的完全相同的函数也是虚函数。可以加virtual以示清晰(也可不加)
4)定义一个父类的指针,将子类对象地址赋给父类的指针,通过该指针调用虚函数,调用的就是所指向子类中的虚函数
5)子类中覆写的函数可以是任意访问类型,依需求而定。
实验代码:
#include <iostream>using namespace std;class shape{public: shape(int x = 0, int y = 0) :_x(x),_y(y){} virtual void draw() { cout<<"drawfrom"<<"("<<_x<<","<<_y<<")"<<endl; }protected: int _x; int _y;};class Circle:public shape{public: Circle(int x = 0, int y= 0, int r = 0) :shape(x,y),_radius(r){} virtual void draw() { cout<<"drawfrom"<<"("<<_x<<","<<_y<<")"; cout<<" _radius ="<<_radius<<endl; }private: int _radius;};class Rec:public shape{public: Rec(int x = 0, int y = 0,int len = 0, int wid = 0 ) :shape(x,y),_len(len),_wid(wid){} virtual void draw() { cout<<"drawfrom"<<"("<<_x<<","<<_y<<")"; cout<<" _len ="<<_len<<" _wid= "<<_wid<<endl; }private: int _len; int _wid;};int main(){ Circle c(1,2,3); c.draw(); Rec r(1,2,3,4); r.draw(); shape *ps = NULL; int choice; while(1) { scanf("%d",&choice); switch(choice) { case 1: ps = &c; ps->draw(); break; case 2: ps = &r; ps->draw(); break; } } return 0;}
3.
virtual void draw() = 0;纯虚函数格式1.含有纯虚函数的类,称为抽象基类,不可实列化。即不能创建对象,存在的意义就是被继承,提供族类的公共接口,java 中称为 interface;2. 纯虚函数只有声明,没有实现,被“初始化”为 0;3. 如果一个类中声明了纯虚函数,而在派生类中没有对该函数定义,则该虚函数在派生类中仍然为纯虚函数,派生类仍然为纯虚基类。
#include <iostream>using namespace std;class shape{public: shape(int x = 0, int y = 0) :_x(x),_y(y){} virtual void draw() = 0;protected: int _x; int _y;};class Circle:public shape{public: Circle(int x = 0, int y= 0, int r = 0) :shape(x,y),_radius(r){} virtual void draw() { cout<<"drawfrom"<<"("<<_x<<","<<_y<<")"; cout<<" _radius ="<<_radius<<endl; }private: int _radius;};class Rec:public shape{public: Rec(int x = 0, int y = 0,int len = 0, int wid = 0 ) :shape(x,y),_len(len),_wid(wid){} virtual void draw() { cout<<"drawfrom"<<"("<<_x<<","<<_y<<")"; cout<<" _len ="<<_len<<" _wid= "<<_wid<<endl; }private: int _len; int _wid;};int main(){ Circle c(1,2,3); Rec r(3,4,5,6); shape *ps = &c; ps->draw(); ps = &r; ps->draw(); return 0;}
4.虚析构(在析构器前加virtual)
目的:为了析构完全,在delete父类指针的时候,会调用子类的析构函数,实现完整析构。
使用方法:当一个类中有虚函数的时候,将其析构函数一并加上virtual
实验代码:
//animal.h#ifndef ANIMAL_H#define ANIMAL_Hclass Animal{public: Animal(); virtual ~Animal(); //如果不加virtual,在释放堆内存的时候只会对Animai进行析构, virtual void voice() = 0; //Animal指针指向的内存不会自动完成析构};#endif // ANIMAL_H
//cat.h#ifndef CAT_H#define CAT_H#include "animal.h"class Cat:public Animal{public: Cat(); ~Cat(); virtual void voice();};#endif // CAT_H
//dog.h#ifndef DOG_H#define DOG_H#include "animal.h"class Dog:public Animal{public: Dog(); ~Dog(); void voice();};#endif // DOG_H
//animal.cpp#include "animal.h"#include <iostream>using namespace std;Animal::Animal(){ cout<<"Animal()"<<endl;}Animal::~Animal(){ cout<<"~Animal()"<<endl;}
//cat.cpp#include "cat.h"#include <iostream>using namespace std;Cat::Cat(){ cout<<"Cat()"<<endl;}Cat::~Cat(){ cout<<"~Cat()"<<endl;}void Cat::voice(){ cout<<"I am a cat,miao miao miao"<<endl;}
//dog.cpp#include "dog.h"#include <iostream>using namespace std;Dog::Dog(){ cout<<"Dog()"<<endl;}Dog::~Dog(){ cout<<"~Dog()"<<endl;}void Dog::voice(){ cout<<"I am a dog,wang wang wang"<<endl;}
//main.cpp#include <iostream>#include "animal.h"#include "cat.h"#include "dog.h"using namespace std;int main(){ Dog d; Cat c; Animal *a1 = &d; Animal *a2 = &c; a1->voice(); a2->voice(); Animal *a = new Dog; delete a; return 0;}
5.基于多态的依赖倒置设计原则
依赖倒置定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象
下面以两种不同的程序设计方法来表达设计思想
场景是这样的,母亲给孩子讲故事,只要给她一本书,她就可以照着书给孩子讲故事了。
传统过程设计:
#include <iostream>using namespace std;class Book{public: string getContents() { return "A little bear are crying"; }};class News{public: string getContents() { return "Mr.Zhou were awarded with the Noble Prize"; }};class Mother{public: void tellContents(Book *b) { cout<<b->getContents()<<endl; } void tellContents(News *n) { cout<<n->getContents()<<endl; }};int main(){ Mother m; Book b; News n; m.tellContents(&b); m.tellContents(&n); return 0;}
#include <iostream>using namespace std;class Ireader{public: virtual string getContents() = 0;};class Book:public Ireader{public: virtual string getContents() { return "A little bear are crying"; }};class News:public Ireader{public: virtual string getContents() { return "Mr.Zhou were awarded with the Noble Prize"; }};class Mother{public: void tellContents(Ireader *i) { cout<<i->getContents()<<endl; }};int main(){ Mother m; Book b; News n; m.tellContents(&b); m.tellContents(&n); return 0;}
电脑组装实验代码:
#include <iostream>using namespace std;class CPU{public: virtual void run() = 0;};class Mem{public: virtual void run() = 0;};class Disk{public: virtual void run() = 0;};class Intel:public CPU{public: virtual void run() { cout<<"Intel CPU"<<endl; }};class Kingston:public Mem{public: virtual void run() { cout<<"Kingston Mem"<<endl; }};class Wddisk:public Disk{public: virtual void run() { cout<<"Wddisk"<<endl; }};class Computer{public: Computer(CPU *pc,Mem *pm,Disk *pd) :_pc(pc),_pm(pm),_pd(pd){} void work() { _pc->run(); _pm->run(); _pd->run(); } ~Computer() { delete _pc; delete _pm; delete _pd; }private: CPU *_pc; Mem *_pm; Disk *_pd;};int main(){ Computer c(new Intel,new Kingston,new Wddisk); c.work(); return 0;}
- C++学习之路 day8
- python自动化之路-day8
- Android学习之Java基础篇day8
- python自动化之路-day8.1
- python学习-Day8-python流程控制之if、for、which、
- C语言:Day7~Day8
- java学习笔记day8
- Android学习笔记day8
- java学习day8
- python学习日志--day8
- 机器学习学习笔记.day8
- day8,9 c语言作业
- day8
- DAY8
- Day8
- DAY8
- Day8
- day8
- Needleman/Wunsch算法介绍以及JAVA代码编写
- [7-01]jdbc
- 华罗庚数学竞赛如何报名?
- Bootstrap3.0学习第一轮(入门)
- JavaScript工具库之Lodash
- C++学习之路 day8
- 【Gym
- java类的访问权限
- Gson基本操作,JsonObject,JsonArray,String,JavaBean,List互转
- Ureport2 ---报表设计(2)--报表计算模型
- XAMPP中MySQL和本地MySQL冲突的
- 解析from distutils.version import LooseVersion
- TCP/IP 协议 总结一
- Android 7.0 广播导致的crash问题