zoukankan      html  css  js  c++  java
  • C++ 第八天


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

  • 相关阅读:
    访问localhost:8080 提示:位于 XDB 的服务器 localhost 要求用户名和密码 (引用)
    jdk在Windows下为什么要配置环境变量(引用)
    Eclipse 应用的初步认识
    linux awk命令
    CentOS7装好了开始装wrf了
    VMware 虚拟机安装 + Cent OS 7的下载与安装
    准备学习wrf
    全面学习ORACLE Scheduler特性(2)管理jobs
    全面学习ORACLE Scheduler特性(1)创建jobs
    Spring-MVC环境搭建
  • 原文地址:https://www.cnblogs.com/Malphite/p/10017631.html
Copyright © 2011-2022 走看看