C++ 视频课笔记7

来源:互联网 发布:js手机端touch事件 编辑:程序博客网 时间:2024/06/01 22:59
在父类Shape,和子类Circle,子类Rect的虚构函数前加 virtual 变为virtual ~Shape();virtual ~Circle();virtual ~Rect(); 则问题就得以解决



5.3虚函数和虚析构函数原理
虚函数
指针指向函数地址——函数指针,一个指针占4个内存大小。

         

函数的覆盖和隐藏(可能面试题)
如上图,在子类当中没有定义同名的虚函数时,函数指针的入口地址就是和父类相同的,如果在子类当中定义了同名的虚函数,则子类的同名函数的入口地址就会变成子函数自己的,和父类不同,也就是会覆盖父类的函数指针的值

虚析构函数
理论前提:执行完子类的析构函数就会执行父类的析构函数

     

5.4纯虚函数抽象类
virtual double calcPerimeter() = 0;没有结构体,后面要加 = 0的虚函数叫纯虚函数。
包含纯虚函数的类叫做 抽象类 , 抽象类无法实例化对象,因为在虚函数列表中,纯虚函数直接地址是0,无法调用。抽象类的子类也可以是抽象类。


5.5接口类
仅含有纯虚函数的类称为接口类(类中无数据成员,也无构造和析构函数,只有成员函数,且成员函数都是纯虚函数
接口类更多的是表达一种能力或协议

5.6运行时类型识别(RTTI)

typeid——dynamic_cast

dynamic_cast注意事项:
1.只能应用于指针和引用的转换
2.要转换的类型中必须包含虚函数
3.转换成功返回子类的地址,失败返回NULL

typeid注意事项
1.type_id返回一个type_info对象的引用
2.如果想通过基类的指针获得派生类的数据类型,基类必须带有虚函数
3.只能获取对象的实际类型

#include<iostream>
#include<stdlib.h>
#include<string>
#include"Plane.h"
#include"Bird.h"
using namespace std;

/* RTTI
     1.Flyable类,成员函数:take off、land
     2.Plane类,成员函数:take off、land、carry
     3.Bird类,成员函数:take off、land、foraging
     4.全局函数doSomething(Flyable *obj)        */

void doSomething(Flyable *obj)
{
     cout << typeid(*obj).name() << endl; //可返回变量的类型名称
     obj->takeoff();
     if (typeid(*obj) == typeid(Bird))
     {
          Bird *bird = dynamic_cast<Bird *>(obj);
              bird->foraging();
     }

     if (typeid(*obj) == typeid(Plane))
     {
          Plane *plane = dynamic_cast<Plane *>(obj);
          plane->carry();
     }
     obj->land();
}
int main()
{
     Flyable *p = new Bird();
     cout << typeid(p).name() << endl;
     cout << typeid(*p).name() << endl;
     Bird b;
     Plane a;
     doSomething(&b);
     doSomething(&a);
     system("pause");
     return 0;
}

#ifndef FLYABLE_H
#define FLYABLE_H
#include<iostream>
class Flyable
{
public:
     virtual void takeoff() = 0;
     virtual void land() = 0;
};

#endif

#ifndef PLANE_H
#define PLANE_H
#include<iostream>
#include"Flyable.h"

class Plane: public Flyable
{
public:
     virtual void takeoff();
     virtual void land();
     virtual void carry();
};

#endif

#include"Plane.h"
using namespace std;

void Plane::takeoff()
{
     cout << "Plane--takeoff" << endl;
}
void Plane::land()
{
     cout << "Plane--land" << endl;
}
void Plane::carry()
{
     cout << "Plane--carry" << endl;
}

#ifndef BIRD_H
#define BIRD_H
#include<iostream>
#include"Flyable.h"

class Bird:public Flyable
{
public:
     virtual void takeoff();
     virtual void land();
     virtual void foraging();
};

#endif

#ifndef BIRD_H
#define BIRD_H
#include<iostream>
#include"Flyable.h"

class Bird:public Flyable
{
public:
     virtual void takeoff();
     virtual void land();
     virtual void foraging();
};

#endif

5.7异常处理
对有可能发生异常的地方做出预见性的安排

关键字:try...catch (尝试...捕获...)   throw(抛出异常)
基本思想:主逻辑与异常处理分离
常见异常:
1.数组下标越界
2.除数为0
3.内存不足(越来越少见)

#include<iostream>
#include<stdlib.h>
#include<string>
#include"IndexException.h"
using namespace std;
void test()
{
     throw IndexException();
}
int main()
{
     try
     {
          test();
     }
     catch (IndexException &a)
     {
          a.printException();
     }
     system("pause");
     return 0;
}

#ifndef EXCEPTION_H
#define EXCEPTION_H
#include<iostream>
class Exception
{
public:
     virtual void printException();
     virtual ~Exception(){}
};
#endif

#include"Exception.h"
#include<iostream>
using namespace std;
void Exception::printException()
{
     cout << "Exception--printException()" << endl;
}

#ifndef INDEXEXCEPTION_H
#define INDEXEXCEPTION_H
#include<iostream>
#include"Exception.h"
class IndexException:public Exception
{
public:
     virtual void printException();
};
#endif

#include"IndexException.h"
#include<iostream>
using namespace std;
void IndexException::printException()
{
     cout << "提示:下标越界。" << endl;
}


原创粉丝点击