virtual用法一

#include 
using namespace std;
class A{
public:
     virtual  void  display(){  cout<<"A"<<ENDL; }
     };
class B :  public A{
public:
            void  display(){ cout<<"B"<<ENDL; }
     };
void doDisplay(A *p)

{
p->display();
delete p;

}

int main(int argc,char* argv[])

{
doDisplay(new B());
return 0;

}

这段代码打印出的结果为B,但是当把A类中的virtual去掉之后打印出的就为A。当基类中没有virtual的时候,编译器在编译的时候把p看做A类的对象,调用的自然就是A类的方法。但是加上virtual之后,将dispaly方法变成了虚方法,这样调用的时候编译器会看调用的究竟是谁的实例化对象,这样就实现了多态的效果。也就是说,当基类的派生类中有重写过基类的虚方法的时候,使用基类的指针指向派生类的对象,调用这个方法实际上调用的会是派生类最后实现的方法

virtual用法二

#include 
using namespace std;
class Person{
   public:    Person(){ cout<<"Person构造"<<ENDL; }
           ~Person(){ cout<<"Person析构"<<ENDL; }
};
class Teacher : virtual public Person{
   public:    Teacher(){ cout<<"Teacher构造"<<ENDL; }
            ~Teacher(){ out<<"Teacher析构"<<ENDL; }
};
class Student : virtual public Person{
  public:      Student(){ cout<<"Student构造"<<ENDL; }
             ~Student(){ cout<<"Student析构"<<ENDL; }
};
class TS : public Teacher,  public Student{
public:            TS(){ cout<<"TS构造"<<ENDL; }
                 ~TS(){ cout<<"TS析构"<<ENDL; }
};
int main(int argc,char* argv[])

{
TS ts;
return 0;

}

这段代码的终端输出结果为:
Person构造
Teacher构造
Student构造
TS构造
TS析构
Student析构
Teacher析构
Person析构
当Teacher类和Student类没有虚继承Person类的时候,也就是把virtual去掉时候终端输出的结果为:
Person构造
Teacher构造
Person构造
Student构造
TS构造
TS析构
Student析构
Person析构
Teacher析构
Person析构
     大家可以很清楚的看到这个结果明显不是我们所期望的。我们在构造TS的时候需要先构造他的基类,也就是Teacher类和Student类。而Teacher类和Student类由都继承于Person类。这样就导致了构造TS的时候实例化了两个Person类。同样的道理,析构的时候也是析构了两次Person类,这是非常危险的,也就引发出了virtual的第三种用法,虚析构。

virtual用法三

#include 
using namespace std;
class Person{
 public:        Person()  {name = new char[16];cout<<"Person构造"<<ENDL;}
      virtual  ~Person()  {delete []name;cout<<"Person析构"<<ENDL;}
 private:
         char *name;
         };
class Teacher :virtual public Person{
public:         Teacher(){ cout<<"Teacher构造"<<ENDL; }
              ~Teacher(){ cout<<"Teacher析构"<<ENDL; }
};
class Student :virtual public Person{
public:         Student(){ cout<<"Student构造"<<ENDL; }
              ~Student(){ cout<<"Student析构"<<ENDL; }
};
class TS : public Teacher,public Student{
public:             TS(){ cout<<"TS构造"<<ENDL; }
                 ~TS(){ cout<<"TS析构"<<ENDL; }
};
int main(int argc,char* argv[])

{
Person *p = new TS();
delete p;
return 0;

}

这段代码的运行结果为:
Person构造
Teacher构造
Student构造
TS构造
TS析构
Student析构
Teacher析构
Person析构
但是当我们把Person类中析构前面的virtual去掉之后的运行结果为:
Person构造
Teacher构造
Student构造
TS

virtual 三种用法的更多相关文章

  1. C++学习---- virtual的三种用法

    virtual用法一:多态 #include<iostream> using namespace std; class A{ public: virtual void display(){ ...

  2. using 的三种用法

    using 有哪三种用法? 1)引入命名空间. 2)给命名空间或者类型起别名. 3)划定作用域.自动释放资源,使用该方法的类型必须实现了 System.IDisposable接口,当对象脱离作用域之后 ...

  3. Js闭包常见三种用法

        Js闭包特性源于内部函数可以将外部函数的活动对象保存在自己的作用域链上,所以使内部函数的可以将外部函数的活动对象占为己有,可以在外部函数销毁时依然存有外部函数内的活动对象内容,这样做的好处是可 ...

  4. .NET(c#)new关键字的三种用法

    前几天去家公司面试,有一道这样的题:写出c#中new关键字的三种用法,思前想后挖空心思也只想出了两种用法,回来查了下msdn,还真是有第三种用法:用于在泛型声明中约束可能用作类型参数的参数的类型,这是 ...

  5. SQL、LINQ、Lambda 三种用法(转)

    SQL.LINQ.Lambda 三种用法颜色注释: SQL LinqToSql Lambda QA1. 查询Student表中的所有记录的Sname.Ssex和Class列.select sname, ...

  6. c# new关键字的三种用法

    三种用法如下: 在 C# 中,new 关键字可用作运算符.修饰符或约束. 1)new 运算符:用于创建对象和调用构造函数. 2)new 修饰符:在用作修饰符时,new 关键字可以显式隐藏从基类继承的成 ...

  7. java中 this 的三种用法

    Java中this的三种用法 调用属性 (1)this可以调用本类中的任何成员变量 调用方法(可省略) (2)this调用本类中的成员方法(在main方法里面没有办法通过this调用) 调用构造方法 ...

  8. 子查询。ANY三种用法。ALL两种用法。HAVING中使用子查询。SELECT中使用子查询。

    子查询存在的意义是解决多表查询带来的性能问题. 子查询返回单行多列: ANY三种用法: ALL两种用法: HAVING中的子查询返回单行单列: SELECT中使用子查询:(了解就好,避免使用这种方法! ...

  9. java中 this 关键字的三种用法

    Java中this的三种用法 调用属性 (1)this可以调用本类中的任何成员变量 调用方法(可省略) (2)this调用本类中的成员方法(在main方法里面没有办法通过this调用) 调用构造方法 ...

随机推荐

  1. (转载)23种设计模式的uml图表示及通俗介绍

    转载自: https://www.cnblogs.com/ningskyer/articles/3615312.html 0.分类 创建型模式 1.FACTORY2.BUILDER3.FACTORY ...

  2. Oracle listener.ora 设置

  3. pc端常见布局---垂直居中布局 单元素不定高

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  4. npm在linux即mac下更新时报错

    nam在linux即mac下需要更新到新版本:

  5. 【Python图像特征的音乐序列生成】思路的转变

    关于生成网络这边,可能会做一个深度的受限玻尔兹曼机,这样可以保证生成的音乐不会太相似. 情绪识别网络和生成网络的耦合,中间变量可能直接就是一个one-hot向量,用来标注指定的情绪,不做成坐标那种难以 ...

  6. CF Gym 100463D Evil (二维前缀和+离散)

    题意:给一些带颜色的点,求一个最小的矩形,恰好包括一半的红色点,且不包括蓝色点. 题解:暴力,求个二维前缀和,用容斥原理更新一下.N很小所以我采用了离散优化,跑了个0ms. 之前没写过二维前缀和,加上 ...

  7. Jquery库插件大全(工作中遇到总结)

    Jquery UI所有插件下载:http://jqueryui.com/download/all/ Jquery layer灯箱等演示与帮助:http://sentsin.com/jquery/lay ...

  8. opencv中mat的type

    type表示了矩阵中元素的类型以及矩阵的通道个数,它是一系列的预定义的常量,其命名规则为CV_(位数)+(数据类型)+(通道数),由type()返回,但是返回值是int型,不是OpenCV预定义的宏( ...

  9. lca(最近公共祖先(在线)) 倍增法详解

    转自大佬博客 : https://blog.csdn.net/lw277232240/article/details/72870644 描述:倍增法用于很多算法当中,通过字面意思来理解 LCA是啥呢 ...

  10. js判断是否为app

    var ua = navigator.userAgent; var isapp = ua.match("lenovomallapp") == null ? 0 : 1;