为了访问公有派生类的特定成员,可以通过讲基类指针显示转换为派生类指针。

也可以将基类的非静态成员函数定义为虚函数(在函数前加上virtual

 #include<iostream>
using namespace std; class base{
public:
/*virtual*/ void who(){ //define this function to virtual will be normal
cout << "this is the class of base !" << endl;
}
}; class derive1:public base{
public:
void who(){
cout << "this is the class of derive1 !" << endl;
}
};
class derive2 :public base{
public:
void who(){
cout << "this is the class of derive2 !" << endl;
}
};
int main(){
base beseObject, *p;
derive1 obj1;
derive2 obj2;
p = &beseObject;
p->who();
cout << "------------------------------" << endl;
p = &obj1;
p->who();
((derive1*)p)->who();
cout << "------------------------------" << endl;
p = &obj2;
p->who();
((derive2*)p)->who();
cout << "------------------------------" << endl;
obj1.who();
obj2.who();
int i;
cin >> i;
return ;
}

两次结果比较: 没加virtual:;加virtual后:

与重载的关系:

 #include<iostream>
using namespace std; class base{
public:
virtual void f1(){ //virtual function
cout << "f1 function of base " << endl;
}
virtual void f2(){ //virtual function
cout << "f2 function of base " << endl;
}
virtual void f3(){ //virtual function
cout << "f3 function of base " << endl;
}
void f4(){
cout << "f4 function of base " << endl;
}
}; class derive:public base{
public:
void f1(){ //virtual function
cout << "f1 function of derive " << endl;
}
virtual void f2(int x){ //lose virtual characteristic
cout << "f2 function of derive " << endl;
}
//f3(){ //wrong, not the same return type
// cout << "f3 function of base " << endl;
//}
void f4(){ //normal overload
cout << "f4 function of derive " << endl;
}
};
int main(){
base obj1, *ptr;
derive obj2;
ptr = &obj1;
ptr->f1();
ptr->f2();
ptr->f3();
ptr = &obj2;
ptr->f1();
ptr->f2();
ptr->f4();
int i;
cin >> i;
return ;
}

结果:

空虚函数在中间类里必须声明,以保证其后的派生类能使用该虚函数。建立一条从虚函数到派生类的虚函数路径。

 #include<iostream>
using namespace std; class base{
public:
virtual void print(){
cout << "calss base!" << endl;
}
};
class son:public base{
public:
virtual void print(){ //empty virtual class
}
};
class grandson :public son{
public:
void print(){
cout << "calss grandson!" << endl;
}
};
void show(base* b){
b->print();
}
int main(){
base *pbase = new base;
son *pson = new son;
grandson *pgrandson = new grandson;
show(pbase);
show(pson);
show(pgrandson);
int i;
cin >> i;
return ;
}

结果:

存虚函数与抽象类

 #include<iostream>
using namespace std; class shape{ //抽象类里必须有一个纯虚函数
public:
virtual float area() = ;
};
class triangle :public shape{
protected:
float h, w;
public:
triangle(float hh, float ww){
h = hh; w = ww;
}
float area(){
return h*w*0.5;
}
};
class rectangle :public shape{
protected:
float h, w;
public:
rectangle(float hh, float ww){
h = hh; w = ww;
}
float area(){
return h*w;
}
};
float total(shape* s[], int n){
float sum = ;
for (int i = ; i < n - ; i++)
sum += s[i]->area();
return sum;
}
int main(){
shape* s[];
s[] = new triangle(, );
s[] = new rectangle(, );
float sum = total(s, );
cout <<"total area is: "<< sum << endl;;
int i;
cin >> i;
return ;
}

结果:算出总面积 为 6

虚函数的使用 以及虚函数与重载的关系, 空虚函数的作用,纯虚函数->抽象类,基类虚析构函数使释放对象更彻底的更多相关文章

  1. 构造函数为什么不能为虚函数 &amp; 基类的析构函数为什么要为虚函数

    一.构造函数为什么不能为虚函数 1. 从存储空间角度,虚函数相应一个指向vtable虚函数表的指针,这大家都知道,但是这个指向vtable的指针事实上是存储在对象的内存空间的.问题出来了,假设构造函数 ...

  2. C++基类的析构函数定义为虚函数的原因

    1:每个析构函数只会清理自己的成员(成员函数前没有virtual).2:可能是基类的指针指向派生类的对象,当析构一个指向派生类的成员的基类指针,这时程序不知道这么办,可能会造成内存的泄露,因此此时基类 ...

  3. C++ 由虚基类 虚继承 虚函数 到 虚函数表

    //虚基类:一个类可以在一个类族中既被用作虚基类,也被用作非虚基类. class Base1{ public: Base1(){cout<<"Construct Base1!&q ...

  4. C++中基类的析构函数为什么要用virtual虚析构函数

    知识背景 要弄明白这个问题,首先要了解下C++中的动态绑定. 关于动态绑定的讲解,请参阅:  C++中的动态类型与动态绑定.虚函数.多态实现 正题 直接的讲,C++中基类采用virtual虚析构函数是 ...

  5. 读书笔记 effective c++ Item 7 在多态基类中将析构函数声明为虚析构函数

    1. 继承体系中关于对象释放遇到的问题描述 1.1 手动释放 关于时间记录有很多种方法,因此为不同的计时方法创建一个TimeKeeper基类和一些派生类就再合理不过了: class TimeKeepe ...

  6. 基类的析构函数写成virtual虚析构函数

    虚函数作用:动态绑定,实现多态效果. 场景问题: 派生类中有资源需要回收,而在编程中采用多态,由基类的指针指向派生类,则在释放的时候,如果基类的析构函数不是virtual,则派生类的析构函数得不到释放 ...

  7. C++中基类虚析构函数的作用及其原理分析

    虚析构函数的理论前提是 执行完子类的析构函数,那么父类的虚构函数必然会被执行. 那么当用delete释放一个父类指针所实例化的子类对象时,如果没有定义虚析构函数,那么将只会调用父类的析构函数,而不会调 ...

  8. 【C++】C++中基类的析构函数为什么要用virtual虚析构函数?

    正面回答: 当基类的析构函数不是虚函数,并且基类指针指向一个派生类对象,然后通过基类指针来删除这个派生类对象时,如果基类的析构函数不是虚析构函数,那么派生类的析构函数就不会被调用,从而产生内存泄漏 # ...

  9. C++-基类的析构函数为什么要加virtual虚析构函数(转)

    知识背景 要弄明白这个问题,首先要了解下C++中的动态绑定. 关于动态绑定的讲解,请参阅:  C++中的动态类型与动态绑定.虚函数.多态实现 正题 直接的讲,C++中基类采用virtual虚析构函数是 ...

随机推荐

  1. jsp九大内置对象

    application例如用于计算网站访问量时可用到.

  2. iOS网络编程

    今天的重点是UIWebView.NSURLSession.JSon. 网络编程联网准备:1.在Info.plist中添加AppTransportSecurity类型Dictionary:2.在AppT ...

  3. atom无法安装插件的解决方法之一

    atom通过setting中无法下载插件,通过apm也无法下载插件,可能是网络.config配置的问题,不好解决. 下面的方法全手动,基本属于万金油方法: 1,在atom的setting页面中点击op ...

  4. [LeetCode] Remove Duplicates from Sorted List 移除有序链表中的重复项

    Given a sorted linked list, delete all duplicates such that each element appear only once. For examp ...

  5. [LeetCode] Divide Two Integers 两数相除

    Divide two integers without using multiplication, division and mod operator. If it is overflow, retu ...

  6. websocket初探

    本文尚未完成,在此只写一些句子,以后慢慢整理. 一.参数 IllegalArgumentException No payload parameter present on the method[mes ...

  7. C#工程引用自定义目录的DLL

    在App.config里配置: <configuration> <runtime> <assemblyBinding xmlns="urn:schemas-mi ...

  8. StringHelper

    /// <summary> /// 文本取左边 /// </summary> /// <param name="str"></param& ...

  9. python学习之路 第六天

    1.正则表达式 re.match() 从头匹配: re.match("[0-9]","123abc789") 只匹配一个数字: re.match("[ ...

  10. 贝塔阶段html及pdf模块测试

    这次虽然工作内容是将c#的html及pdf处理程序移植到java中,但是由于重新编写代码使得先前的工作成果得不到利用,于是将其编写为dll,再在java端调用. 这使得在java端即便每个分支都到达, ...