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. 事务的隔离级别和mysql事务隔离级别修改

    A事务做了操作 没有提交 对B事务来说 就等于没做 获取的都是之前的数据 但是 在A事务中查询的话 查到的都是操作之后的数据 没有提交的数据只有自己看得到,并没有update到数据库. 查看InnoD ...

  2. BZOJ4299: Codechef FRBSUM(主席树)

    题意 题目链接 数集S的ForbiddenSum定义为无法用S的某个子集(可以为空)的和表示的最小的非负整数. 例如,S={1,1,3,7},则它的子集和中包含0(S’=∅),1(S’={1}),2( ...

  3. nmap扫描开放端口

    nmap 192.168.1.1  -p1-65535 指定端口范围使用-p参数,如果不指定要扫描的端口,Nmap默认扫描从1到1024再加上nmap-services列出的端口 nmap-servi ...

  4. AngularJS所有版本下载地址

    AngularJS官网本身采用AngularJS库构建,页面中的AngularJS库通过Google的CDN(内容分发网络)引入,所以国内访问会有问题. 大家可以从下面地址获取AngularJS所以版 ...

  5. nmap -sT

    将与目标端口进行三次握手,尝试建立连接,如果连接成功,则端口开放,慢,且会被目录主机记录

  6. 洛谷 P2038 无线网络发射器选址

    题目描述 随着智能手机的日益普及,人们对无线网的需求日益增大.某城市决定对城市内的公共场所覆盖无线网. 假设该城市的布局为由严格平行的129 条东西向街道和129 条南北向街道所形成的网格状,并且相邻 ...

  7. 如何在Netweaver SE16里直接查看某数据库行记录

    有的数据库表字段类型为RAWSTRING, 包含的是XML的二进制内容,无法直接在SE16里显示. 如果确实想看其内容,怎么办?在下面SE16页面的命令提示栏输入命令/h, 回车进入调试模式.然后双击 ...

  8. ceisum_加载倾斜摄影模型

    osgb转换为3Dtiles格式(使用工具转换) 然后加载到cesium中(加载代码见下,可以控制模型高度) var offset = function(height,tileset) { conso ...

  9. Codeforces Round #320 (Div. 1) [Bayan Thanks-Round] A A Problem about Polyline(数学)

    题目中给出的函数具有周期性,总可以移动到第一个周期内,当然,a<b则无解. 假设移动后在上升的那段,则有a-2*x*n=b,注意限制条件x≥b,n是整数,则n≤(a-b)/(2*b).满足条件的 ...

  10. 2017年团体程序设计天梯赛 - 大区赛 L3-3

    题意:有向图找哈密顿回路 比赛的时候剪枝只剪了vis 状压没剪对 反而只拿17分... 比赛结束后还去看了一发这个NP问题的QB(快速回溯法...但是对于本题好像大材小用...) 上网看了一个神犇的写 ...