您的位置:首页 > 编程语言 > C语言/C++

c++ primer plus阅读笔记13---虚函数 为什么要虚析构函数?

2017-08-17 17:16 232 查看
虚函数

虚函数主要是用来实现动态多态的,我们来看下边的代码:

class Base
{
...
public:
void function()
{
...
}
};
class Extends:public Base
{
...
public:
void function()
{
...
}
};
int main()
{
Base base;
Extends extends;
Base &b1=base;
Base &b2=extends;  //父类的引用指向子类,向上转型
b1.fuctione(); //相当于:Base::function();
b2.function(); //相当于:Base::function();
}


如果没有使用关键字virtual,程序将根据引用类型指针类型来选择方法,main函数中,b1,b2的引用类型都是Base,所以调用的是父类的function方法;

如果在父类的function的定义前边加上关键字virtual,则调用b2.function()相当于:Extends::function();

class Base
{
public:
//加了关键字virtual以后,这个函数成了虚函数,此时子类的function也成了虚函数,但是子类的virtual可以省略,
virtual void function()
{
std::cout<<"调用了父类的function方法"<<std::endl;
}
};

class Extends:public Base
{
public:
void function()
{
std::cout<<"调用了子类的function方法"<<std::endl;
}
};

int main()
{
Base base;
Extends extends;
Base &b1=base;
Base &b2=extends;
b1.function();
b2.function(); //相当于:Extends::function();
}


为何要使用虚函数?

加了关键字virtual以后,将会根据对象的实际类型来选择调用的函数。

我们在堆上申请一块内存存放子类的对象,并且使用父类的指针指向它,当我们是放这块内存的时候,需要调用这块内存对象的析构函数,但是我们使用的是父类的指针指向了它,如果析构函数没有不是虚析构函数,则会调用父类的析构函数,不会调用子类的析构函数。如果在子类的构造函数申请一块内存,并且在析构函数中释放这块内存,如果子类的析构函数没有被调用,将会造成内存泄露。因此需要在父类的析构函数上加上关键字virtual,这样调用析构函数的时候,会调用实际对象的类型的析构函数,如下代码:

class Base
{
public:
virtual void function()
{
std::cout<<"调用了父类的function方法"<<std::endl;
}
~Base()
{
std::cout<<"调用了父类的析构函数"<<std::endl;
}
};

class Extends:public Base
{
public:
Extends()
{
std::cout<<"调用了子类的构造函数"<<std::endl;
p=new int(20); //如果父类的析构函数不是虚析构函数,则以main函数中的方式释放内存,只调用了父类的析构函数,这块内存无法释放,造成内存泄露。
for(int i=0;i<20;i++)
{
*(p+i)=i;
}
}

void function()
{
std::cout<<"调用了子类的function方法"<<std::endl;
}
void test()
{
std::cout<<"调用了子类的特有函数"<<std::endl;
}

void show()
{
for(int i=0;i<20;i++)
{
std::cout<<*(p+i)<<std::endl;
}
}
~Extends()
{
std::cout<<"调用了子类的析构函数"<<std::endl;
}

private:
int *p;
};

int main()
{
Base *base=new Extends();
base->function();
delete base; //销毁base指向的对象,调用其析构函数,这里只会调用父类的析构函数,造成子类中的p指针指向的内存泄露。

}


上边这个例子阐述了虚析构函数的重要性。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: