c++面向接口编程,虚函数,虚析构函数
2010-12-25 11:48
288 查看
基类:
People.h
People.cpp
派生类:
Student.h
Student.cpp
Teacher.h
Teacher.cpp
main.cpp
虚析构函数是为了解决这样的一个问题:基类的指针指向派生类对象,并用基类的指针删除派生类对象。
如果某个类不包含虚函数,那一般是表示它将不作为一个基类来使用。当一个类不准备作为基类使用时,使析构函数为虚一般是个坏主意。因为它会为类增加一个虚函数表,使得对象的体积翻倍,还有可能降低其可移植性。
所以基本的一条是:无故的声明虚析构函数和永远不去声明一样是错误的。实际上,很多人这样总结:当且仅当类里包含至少一个虚函数的时候才去声明虚析构函数。
抽象类是准备被用做基类的,基类必须要有一个虚析构函数,纯虚函数会产生抽象类,所以方法很简单:在想要成为抽象类的类里声明一个纯虚析构函数。
这里是一个例子:
class awov { // awov = "abstract w/o
// virtuals"
public:
virtual ~awov() = 0; // 声明一个纯虚析构函数
};
这个类有一个纯虚函数,所以它是抽象的,而且它有一个虚析构函数,所以不会产生析构函数问题。但这里还有一件事:必须提供纯虚析构函数的定义:
awov::~awov() {} // 纯虚析构函数的定义
这个定义是必需的,因为虚析构函数工作的方式是:最底层的派生类的析构函数最先被调用,然后各个基类的析构函数被调用。这就是说,即使是抽象类,编译器也要产生对~awov的调用,所以要保证为它提供函数体。如果不这么做,链接器就会检测出来,最后还是得回去把它添上。
注意:如果声明虚析构函数为inline,将会避免调用它们时产生的开销,但编译器还是必然会在什么地方产生一个此函数的拷贝。
People.h
#pragma once class People { public: People(void); virtual ~People(void); virtual void show(); };
People.cpp
#include "People.h" #include <iostream> using namespace std; People::People(void) { cout<<"People"<<endl; } People::~People(void) { cout<<"~People"<<endl; } void People::show() { cout<<"People show"<<endl; }
派生类:
Student.h
#pragma once #include "People.h" class Student :public People { public: Student(void); ~Student(void); void show(); };
Student.cpp
#include "Student.h" #include <iostream> using namespace std; Student::Student(void) { cout<<"student"<<endl; } Student::~Student(void) { cout<<"~student"<<endl; } void Student::show() { cout<<"student show"<<endl; }
Teacher.h
#pragma once #include "People.h" class Teacher:public People { public: Teacher(void); ~Teacher(void); void show(); };
Teacher.cpp
#include "Teacher.h" #include <iostream> using namespace std; Teacher::Teacher(void) { cout<<"Teacher"<<endl; } Teacher::~Teacher(void) { cout<<"~Teacher"<<endl; } void Teacher::show() { cout<<"teacher show"<<endl; }
main.cpp
#include "Student.h" #include "Teacher.h" void main() { People *pObj = new Student();//面向接口编程,修改此句便可以达到更换模块的目的 //People *pObj = new Teacher(); pObj->show(); delete pObj; }
虚析构函数是为了解决这样的一个问题:基类的指针指向派生类对象,并用基类的指针删除派生类对象。
如果某个类不包含虚函数,那一般是表示它将不作为一个基类来使用。当一个类不准备作为基类使用时,使析构函数为虚一般是个坏主意。因为它会为类增加一个虚函数表,使得对象的体积翻倍,还有可能降低其可移植性。
所以基本的一条是:无故的声明虚析构函数和永远不去声明一样是错误的。实际上,很多人这样总结:当且仅当类里包含至少一个虚函数的时候才去声明虚析构函数。
抽象类是准备被用做基类的,基类必须要有一个虚析构函数,纯虚函数会产生抽象类,所以方法很简单:在想要成为抽象类的类里声明一个纯虚析构函数。
这里是一个例子:
class awov { // awov = "abstract w/o
// virtuals"
public:
virtual ~awov() = 0; // 声明一个纯虚析构函数
};
这个类有一个纯虚函数,所以它是抽象的,而且它有一个虚析构函数,所以不会产生析构函数问题。但这里还有一件事:必须提供纯虚析构函数的定义:
awov::~awov() {} // 纯虚析构函数的定义
这个定义是必需的,因为虚析构函数工作的方式是:最底层的派生类的析构函数最先被调用,然后各个基类的析构函数被调用。这就是说,即使是抽象类,编译器也要产生对~awov的调用,所以要保证为它提供函数体。如果不这么做,链接器就会检测出来,最后还是得回去把它添上。
注意:如果声明虚析构函数为inline,将会避免调用它们时产生的开销,但编译器还是必然会在什么地方产生一个此函数的拷贝。
相关文章推荐
- 析构函数虚函数:C++虚函数;虚析构函数;类的存储空间
- 从零开始学C++之虚函数与多态(一):虚函数表指针、虚析构函数、object slicing与虚函数、C++对象模型图
- C++学习:虚函数,纯虚函数(virtual),虚继承,虚析构函数
- C++虚函数与虚析构函数
- C++中 虚函数 虚析构函数的作用
- C++虚函数的实现细节、虚析构函数 汇编解析
- C++虚函数与虚析构函数
- 从零开始学C++之虚函数与多态(一):虚函数表指针、虚析构函数、object slicing与虚函数、C++对象模型图 .
- c++ primer plus阅读笔记13---虚函数 为什么要虚析构函数?
- 从零开始学C++之虚函数与多态(一):虚函数表指针、虚析构函数、object slicing与虚函数、C++对象模型图
- 读书笔记--C++程序设计(第2版)--12多态性与虚函数(虚析构函数,纯虚函数与抽象类)
- 从零开始学C++之虚函数与多态(一):虚函数表指针、虚析构函数、object slicing与虚函数、C++对象模型图
- C++虚函数与虚析构函数
- C++虚函数的实现细节、虚析构函数 汇编解析
- 虚函数与多态(一):虚函数表指针、虚析构函数、object slicing与虚函数、C++对象模型图
- c++ 多态、虚函数、虚析构函数
- 从逆向分析角度看C++虚函数
- C++——多态&虚函数
- C++对象布局及多态实现之带虚函数的类
- C++虚函数的作用