`
v5browser
  • 浏览: 1140227 次
社区版块
存档分类
最新评论

详解C++中的virtual

 
阅读更多

1.virtual 析构函数的作用

析构函数也可以是虚的,甚至是纯虚的。但是构造函数不能是虚的。<wbr style="line-height:25px; color:rgb(46,46,46); font-family:Arial,Helvetica,simsun,u5b8bu4f53; font-size:14px"><span style="color:rgb(46,46,46); font-family:Arial,Helvetica,simsun,u5b8bu4f53; font-size:14px; line-height:25px">例如:</span><br style="line-height:25px; color:rgb(46,46,46); font-family:Arial,Helvetica,simsun,u5b8bu4f53; font-size:14px"></wbr>

class A { public: virtual ~A()=0; // 纯虚析构函数 };

类型需要虚析构函数的另外一个特征是该类型具有指针成员或引用成员。如果有指针成员和引用成员,则该类型通常需要实现析构函数以及拷贝操作。通常,一个实现了析构函数的类型同时也需要实现拷贝构造函数与拷贝复制函数。

作为一个经验法则:如果你有一个带有虚函数功能的类,则它需要一个虚析构函数,原因如下:

1. 如果一个类有虚函数功能,它经常作为一个基类使用。

2.如果它是一个基类,它的派生类经常使用new来分配。

3.如果一个派生类对象使用new来分配,并且通过一个指向它的基类的指针来控制,那么它经常通过一个指向它的基类的指针来删除它(如果基类没有虚析构函数,结果将是不确定的,实际发生时,派生类的析构函数永远不会被调用)。基类有虚析构函数的话,最底层的派生类的析构函数最先被调用,然后各个基类的析构函数被调用。

当一个类打算被用作其它类的基类时,它的析构函数必须是虚的。考虑下面的例子:

class A { public: A() { ptra_ = new char[10];} ~A() { delete[] ptra_;} // 非虚析构函数 private: char * ptra_; }; class B: public A { public: B() { ptrb_ = new char[20];} ~B() { delete[] ptrb_;} private: char * ptrb_; }; void foo() { A * a = new B; delete a; }

  在这个例子中,程序也许不会象你想象的那样运行,在执行delete a的时候,实际上只有A::~A()被调用了,而B类的析构函数并没有被调用!造成内存的泄漏,这是否有点儿可怕?
  如果将上面A::~A()改为virtual,就可以保证B::~B()也在delete a的时候被调用了。因此基类的析构函数都必须是virtual的。

2.virtual继承的作用

避免二义性

如果基类A

B继承A,C继承A

C继承B,C


那么B: public virtual A,

C: public virtual A

如果没有virtual 编译器会报错。有二义性的错误


3.virtual函数

C++多态的精华就是virtual函数。

1.纯虚函数。这个就是virtual void show()=0;类似java中的接口。必须实现。

2.普通虚函数

基类的实现:

#ifndef Memory_C_h
#define Memory_C_h

class C
{
public:
    C()
    {
        NSLog(@"construct c");
    }
    virtual ~C()
    {
        NSLog(@"delete c");
    }
    virtual void show()
    {
        NSLog(@"showC");
    }
private:
    int x;
};

#endif

子类的实现:

#ifndef Memory_D_h
#define Memory_D_h

class D :  public C
{
public:
    D(){
        NSLog(@"construct d");
    }
    ~D()
    {
        NSLog(@"delete D");
    }
    void show()
    {
        NSLog(@"showD");
    }
};

调用的地方:

    C* c = new D;
    c->show();
    
    
    delete c;

结果:

2013-03-12 23:07:14.809 Memory[868:c07] construct c
2013-03-12 23:07:14.810 Memory[868:c07] construct d
2013-03-12 23:07:14.811 Memory[868:c07] showD
2013-03-12 23:07:14.811 Memory[868:c07] delete D
2013-03-12 23:07:14.812 Memory[868:c07] delete c

【注意】虚函数有默认继承的作用,
如果A中有virtual void show();
D继承A,D中 void show();
E继承D,E中 void show();


D* d = new E;
d->show();
delete d;

结果:
2013-03-12 23:13:19.378 Memory[907:c07] construct c
2013-03-12 23:13:19.379 Memory[907:c07] construct d
2013-03-12 23:13:19.379 Memory[907:c07] construct e
2013-03-12 23:13:19.380 Memory[907:c07] showE
2013-03-12 23:13:19.380 Memory[907:c07] delete E
2013-03-12 23:13:19.381 Memory[907:c07] delete D
2013-03-12 23:13:19.381 Memory[907:c07] delete c







分享到:
评论

相关推荐

    详解C++中虚析构函数的作用及其原理分析

    C++中的虚析构函数到底什么时候有用的,什么作用呢。 一.虚析构函数的作用 总的来说虚析构函数是为了避免内存泄露,而且是当子类中会有指针成员变量时才会使用得到的。也就说虚析构函数使得在删除指向子类对象的基类...

    详解C++纯虚函数与抽象类

    为什么说虚函数是C++最重要的特性之一呢,因为虚函数承载着C++中动态联编的作用,也即多态,可以让程序在运行时选择合适的成员函数。虚函数必须是类的非静态成员函数(且非构造函数),其访问权限是public。那么: ...

    C++智能指针详解.pdf

    C++智能指针详解 智能指针详解 智能指针内容很多,重点是基本⽤法。 #include &lt;boost/shared_ptr.hpp&gt; class CBase: public boost::enable_shared_from_this&lt;CBase&gt; { public: virtual void f(){}//必须有个虚函数...

    详解C++ 多态的实现及原理

    C++的多态性用一句话概括就是:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用...

    C++ 中const修饰虚函数实例详解

    C++ 中const修饰虚函数实例详解 【1】程序1 #include using namespace std; class Base { public: virtual void print() const = 0; }; class Test : public Base { public: void print(); }; void Test::print...

    C++100天经典实战系(含大量案例源码及通俗讲解教程,effective_c++、STL、综合能力全面提升)

    友元函数与友元类、引用与指针那些事、深入浅出C++虚函数的vptr与vtable、宏那些事、范围解析运算符那些事、从初级到高级的enum那些事、纯虚函数和抽象类、volatile、virtual、using、union、this、struct_class、...

    C++ 虚函数表解析

    一篇关于C++ 虚函数表解析详解的文章,大家一块学习。 博主还有好多值得阅读的文章,网址http://blog.csdn.net/haoel

    C++ 中函数重载、覆盖与隐藏详解

    C++ 中函数重载、覆盖与隐藏详解 在C++语言中,函数扮演着很重要的角色,不管面向过程设计,还是基于对象设计;不管是面向对象编程,还是基于泛型编程,函数都可以随处而见。在谈论C++中的函数重载、覆盖和隐藏之前...

    详解C++编程中的虚函数

    我们知道,在同一类中是不能定义两个名字相同、参数个数和类型都相同的函数的,否则就是“重复定义”。但是在类的继承层次结构中,在不同的层次中可以出现名字相同、参数个数和类型都相同而功能不同的函数。 人们...

    详解C++成员函数的override和final说明符的用法

    可使用 override 关键字来指定在基类中重写虚函数的成员函数。 语法 function-declaration override; 备注 override 仅在成员函数声明之后使用时才是区分上下文的且具有特殊含义;否则,它不是保留的关键字。 使用...

    C++ 继承详解及实例代码

    C++继承可以是单一继承或多重继承,每一个继承连接可以是public,protected,private也可以是virtual或non-virtual。然后是各个成员函数选项可以是virtual或non-virtual或pure virtual。本文仅仅作出一些关键点的验证...

    从汇编看c++中的多态详解

    在c++中,当一个类含有虚函数的时候,类就具有了多态性。构造函数的一项重要功能就是初始化vptr指针,这是保证多态性的关键步骤。 构造函数初始化vptr指针 下面是c++源码: class X { private: int i; public: X...

    C++获取类的成员函数的函数指针详解及实例代码

    C++获取类的成员函数的函数指针详解 用一个实际代码来说明。 class A { public: staticvoid staticmember(){cout&lt;&lt;static&lt;&lt;endl;} //static member void nonstatic(){cout&lt;&lt;nonstatic&lt;&lt;...

    C++ override关键字使用详解

    C++ override从字面意思上,是覆盖的意思,实际上在C++中它是覆盖了一个方法并且对其重写,从而达到不同的作用。在我们C++编程过程中,最熟悉的就是对接口方法的实现,在接口中一般只是对方法进行了声明,而我们在...

    关于C++对象继承中的内存布局示例详解

    对C++ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。简称为V-Table。在这个表中,主是要一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其容真实反应...

    C++中typeid实现原理详解

    最近看了boost::any类源码,... virtual ~type_info(); _CRTIMP_PURE bool __CLR_OR_THIS_CALL operator==(const type_info& rhs) const; _CRTIMP_PURE bool __CLR_OR_THIS_CALL operator!=(const type_info& rhs) c

    C++ 类中有虚函数(虚函数表)时 内存分布详解

    对C++ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。简称为V-Table。在这个表中,主是要一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其容真实反应...

    C++子类父类成员函数的覆盖和隐藏实例详解

    C++子类父类成员函数的覆盖和隐藏实例详解 函数的覆盖  覆盖发生的条件: (1) 基类必须是虚函数(使用virtual 关键字来进行声明) (2)发生覆盖的两个函数分别位于派生类和基类 (3)函数名和参数列表必须完全...

    C++面向对象之多态的实现和应用详解

    本文主要给大家介绍的是关于C++面向对象之多态的实现和应用的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。 多态 大家应该都听过C++三大特性之一多态,那么什么多态呢?多态有什么用...

Global site tag (gtag.js) - Google Analytics