day8
一、 多态的底层实现
虚函数 加了virtual修饰的成员函数
虚函数表指针
一个类型只要有虚函数 则这个类型就有一张虚函数表。
同类型的对象共享一张虚函数表
虚函数表
每个元素都是虚函数的地址
当父类型指针 指向子类对象时 先根据对象地址中的前四个字节找到虚函数表的地址
然后根据虚函数表地址 找到对应的虚函数地址,再根据虚函数的地址 找到对应的实现。
#include <iostream>
using namespce std;
class Animal{
public:
virtual void show(){
cout << "animal show" << endl;
}
virtual void fun(){
cout << "animal fun" << endl;
}
};
int main(){
cout << sizeof(Animal) << endl; //4
Animal a;
Animal b;
int *p=reinterpret_cast<int*>(&a);
cout << hex << *p << endl;
int *p1=reinterpret_cast<int*>(&b);
cout << hex << *p1 << endl;
}
二、运行时类型识别
2.1 typeid 获取类型信息
#include <iostream>
#include <typeinfo>
using namespce std;
class Animal{
public:
virtual void show(){
cout << "show()" << endl;
}
};
class Dog:public Animal{
public:
void dogfun(){
cout << "home" << endl;
}
void show(){
cout << "dog show()" << endl;
}
};
class Cat:public Animal{
public:
void catfun(){
cout << "mouse" << endl;
}
void show(){
cout << "cat show()" << endl;
}
};
void testAnimal(Animal* a){
a->show();
/*判定指针指向的及具体类型*/
if(typeid(*a)==typeid(Dog)){
((Dog*)a)->dogfun();
}else if(typeid(*a)==typeid(Dog)){
((Cat*)a)->catfun();
}
}
int main(){
int *pi=new int(100);
cout << typeid(pi).name() << endl;//pi
cout << typeid(*pi).name << endl;//i
Animal *pa=new Dog();
cout << typeid(pa).name() << endl;//p6Animal
cout << typeid(*pa).name << endl;//3Dog
if(typeid(*pa)==typeid(Dog)){
cout << "pa -> dog" << endl;
}
testAnimal(pa);
}
2.2 动态类型转换
dynamic_cast<类型>(对象)
如果成功 返回非NULL指针
如果失败 返回NULL指针
#include <iostream>
using namespce std;
class Animal{
public:
virtual void show(){
cout << "animal show" << endl;
}
};
class Dog:public Animal{
string name;
public:
void show(){
cout << "dog show" << endl;
}
void dogfun(){
cout << "house" << endl;
cout << name << endl;
}
};
class Cat:public Animal{
};
void testAnimal(Animal* a){
if(dynamic_cast<Cat*>(a)){
cout << "cat" << endl;
}
if(dynamic_cast<Dog*>(a)){
cout << "dog" << endl;
((Dog*)a)->dogfun();//必须确定类型才可强转
}
}
int main(){
Animal *pa=new Dog();
testAnimal(pa);
/*需要经过判断才能转成相应的类型*/
((Dog*)pa)->dogfun();
}
三、动态绑定和静态绑定
编译时确定对象还是运行是确定对象
四、抽象类
4.1 不能创建对象的类称之为抽象类。
抽象类除了不能实例化之外,和其他类没有任何区别。
4.2 只要在一个类中出现纯虚函数 则这个类自动成为抽象类。
class Animal{
public:
virtual void show()=0;
};
4.3 子类需要实现纯虚函数 否则子类自动成为抽象类
4.4 除了构造 析构之外 如果一个类的函数都是纯虚函数 则这个类称之为纯抽象类。
五、虚析构函数
Animal *pa=new Dog();
delete pa;
当父类型中有虚函数时 建议把析构函数也设置成虚函数。
#include <ios>
using namespce std;
class Animal{
public:
Animal(){
cout << "Animal ()" << endl;
}
virtual ~Animal(){
cout << "~Animal()" << endl;
}
};
class Dog:public Animal(){
public:
Dog(){
cout << "Dog()" << endl;
}
~Dog(){
cout << "~Dog()" << endl;
}
}
int main(){
Animal *p = new Dog();
}
六、c++中的异常处理
6.1 异常就是一种全新的错误表达方式
exception
6.2 可以使用返回值 表达错误
6.3 可以使用异常表达非正常的信息
有异常抛出的情况下,如果程序采用默认方式,
调用terminate 终止程序。
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespce std;
/*对foo函数 可能会抛出哪些异常做说明*/
int foo()throw(int,double,const char *){
int temp=rand()%4;
if(0==temp){
cout << "normal" << endl;
}else if(1==temp){
throw 1;
}eles if(2==temp){
throw 2.5;
}
}
int main(){
srand(time(NULL));
try{
foo();
}catch(int e){
cout << "int exception" << e << endl;
}catch(double b){
cout << "double exception" << b << endl;
}catch(...){
cout << "未知异常" << endl;
}
cout << "go on " << endl;
}
6.4 异常的说明
/*抛出int 和 double异常*/
void foo()throw(){{
}
/*可能会抛出异常*/
void foo(){
}
/*不抛出任何异常*/
void foo()throw()}{
}
6.5 系统提供的异常
exception //不抛出任何异常
内存分配
#include <iostream>
#include <cstdlib>
using namespce std;
int main(){
void *pi=malloc(0xffffffff);
cout << "pi=" << pi << endl;
try{
int *pii=new int[0xffffffff];
cout << "pii" << pii << endl;
}catch(bad_alloc& e){//基本类型用值捕获,类类型用引用捕获
cout << e.what() << endl;
}
cout << "重新申请内存" << endl;
string abc="hello";
cout << abc[0] << endl;
cout << abc.at(0) << endl;
}
6.6 用户自定义异常
1.定义异常
写异常类 代表不同的问题
2.根据条件 抛出异常
throw 异常;
3.捕获异常
try{
}catch(){
}
4.处理异常
/*异常定义的头文件*/
#ifndef _DMSEXCEPTION_H_
#define _DMSEXCEPTION_H_
#include <string>
using namespce std;
class DmsException{
string msg;
public:
DmsException(string msg="dms exception"):msg(msg){
}
const char* what()const throw(){
return msg.c_str();
}
};
class DmsClientException:public DmsException{
public:
DmsClientException(string msg="dms client exception"):DmsException(msg){
}
};
/*初始化网络异常*/
class DmsInitNetWorkException:public DmsClientException{
public:
DmsInitNetWorkException(string msg=""):DmsClientException(msg){
}
};
/*发送数据异常*/
class DmsSendDataException:public DmsClientException{
public:
DmsSendDataException(string msg=""):DmsClientException(msg){
}
};
#endif //_DMSEXCEPTION_H_
=============================================================================
#include <iostream>
#include <ctime>
#include <cstdlib>
#include "dmsexecprion"
using namespce std;
void initNetWork()throw(DmsInitNetWorkException){
int temp=rand()%2;
if(0 == temp){
cout << "init network success" << endl;
}else if(1==temp){
throw DmsInitNetWorkException("init socket failed");
}else{
throw DmsInitNetWorkException("connect server failed");
}
}
void sendData()throw(DmsInitNetWorkException,DmsSendDataException){
try{
initNetWork();
}catch(DmsInitNetWorkException& e){
/*可以处理也可以用继续上抛*/
throw;
}
while(1){
int temp=rand()%2;
if(0==temp){
cout << "send data success" << endl;
}else{
throw DmsSendDataException("send data failed");
}
}
}
int main(){
srand(time(NUL));
try{
sendData();
}catch(DmsInitNetWorkException& e){
cout << e.what() << endl;
cout << "处理" << endl;
}catch(DmsSendDataException& e){
cout << e.what() << endl;
cout << "结束发送" << endl;
}
}
七 c++ string的使用
构造函数
string();
/*可以使用c字符串构建c++字符串*/
string(const char*);
string(string);
#include <iostream>
#include <cstring>
using namespce std;
int main(){
string stra("hello");
string strb="hello";
if(stra==strb){
cout << "stra==strb" << endl;
}
strb="test";
cout << strb << endl;
/*字符串拼接*/
strb=stra+" hello";
cout << strb << endl;
strb+=" test";
cout << strb << endl;
cout << strb[0] << endl;
/*求字符串长度*/
cour << strb.length() << endl;
/*把c++ 的字符串变成c字符串*/
const char *mystr=strb.c_str();
cout << mystr << endl;
cout << strlen(mystr) << endl;
}