//
// Person.hpp
// test_cpp_protocol_01
//
// Created by jeffasd on 2016/10/23.
// Copyright © 2016年 jeffasd. All rights reserved.
//
#ifndef Person_hpp
#define Person_hpp
#include <string>
class Person
{
public:
Person();
virtual ~Person();
};
// 我们把包含纯虚函数的类称之为抽象类
// 对于抽象类来说,由于其包含纯虚函数,C++是不允许它去实例化对象的。也就是说,抽象类无法实例化对象
// 对于抽象类的子类也可以是抽象类
// 对于抽象类来说,它无法实例化对象,而对于抽象类的子类来说,只有把抽象类中的纯虚函数全部实现之后,那么这个子类才可以实例化对象。
// 定义纯虚函数是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。
class WriteWolrdProtocol
{
public:
/*
* 虚析构:
* 如果一个类用作基类,我们通常需要virtual来修饰它的析构函数,这点很重要。如果基类的析构函数不是虚析构,当我们用delete来释放基类指针(它其实指向的是派生类的对象实例)占用的内存的时候,只有基类的析构函数被调用,而派生类的析构函数不会被调用,这就可能引起内存泄露。如果基类的析构函数是虚析构,那么在delete基类指针时,继承树上的析构函数会被自低向上依次调用,即最底层派生类的析构函数会被首先调用,然后一层一层向上直到该指针声明的类型。
*/
/*
Student *xiaoming = new (std::nothrow) Student;
Person *person = (Person *)xiaoming;
// dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。
// WriteWolrdProtocol *protocol = dynamic_cast<WriteWolrdProtocol *>(person);
WriteWolrdProtocol *protocol = (WriteWolrdProtocol *)(person);
// auto protocol = (WriteWolrdProtocol *)(person);
protocol->writeWorldWithString("hello world");
printf("showName function end\n");
// 如果不定义纯虚函数的析构函数为虚函数 上面代码在执行到protocol->writeWorldWithString("hello world");时 xiaoming对象会被析构 为什么会这样呢?
// 此示例表明:抽象类一定要声明虚析构函数,并且此虚析构函数要定义函数体。
*/
// virtual ~WriteWolrdProtocol() {};
// virtual void writeWorldWithString(const std::string string) = 0; // = 0 告诉编译系统这是纯虚函数 - 子类必须实现 类似OC的@required
virtual void writeWorldWithString(const std::string string) {}; // = 0 告诉编译系统这是纯虚函数 - 子类必须实现 类似OC的@required
virtual void readWorldWithString(const std::string string) {}; // 虚函数 子类可以不实现 类似OC的@optional
};
class Student : public Person, public WriteWolrdProtocol
{
public:
Student();
virtual ~Student();
virtual void writeWorldWithString(const std::string string) override;
};
class Teacher : public Person
{
public:
Teacher();
virtual ~Teacher();
};
#endif /* Person_hpp */