那些函数不可以定义为虚函数呢?现在就让我们了解一下。
1.普通函数。
2.友元函数。
以上两个都不是类的成员函数
4.静态成员函数;虚函数一定要通过对象来调,而静态成员函数不用(说明静态成员函数不在虚表之中)。
5.构造函数;拷贝构造函数(构造函数还没有调就还没有对象,就没有指向虚表的指针,就不可以通过虚表去调用,这是一个先有鸡还是先有蛋的问题)
6.但建议把析构函数给成虚函数(防止内存泄漏),如下代码可以说明这个问题
#include <iostream>
using namespace std;
class Base
{
public:
Base()
{
cout<<"Base::Base()"<<endl;
}
~Base()
{
cout<<"Base::~Base()"<<endl;
}
};
class Derived :public Base
{
public :
Derived()
:_p(new int[10])
{
cout<<"Derived::Derived()"<<endl;
}
~Derived()
{
if (_p)
delete[] _p;
cout<<"Derived::~Derived()"<<endl;
}
int * _p;
};
int main ()
{
Base *pd =new Derived;
delete pd ;
return 0;
}
~
运行之后
调了派生类的构造函数但没有调派生类的析构函数,造成了内存的泄漏
但是如果把Base类中的构造函数改成虚函数,如下
#include <iostream>
using namespace std;
class Base
{
public:
Base()
{
cout<<"Base::Base()"<<endl;
}
virtual ~Base()
{
cout<<"Base::~Base()"<<endl;
}
};
class Derived :public Base
{
public :
Derived()
:_p(new int[10])
{
cout<<"Derived::Derived()"<<endl;
}
~Derived()
{
if (_p)
delete[] _p;
cout<<"Derived::~Derived()"<<endl;
}
int * _p;
};
int main ()
{
Base *pd =new Derived;
delete pd ;
return 0;
}
执行一下,可以看得到
这样就解决了前面的问题。
所以建议把析构函数给成虚函数(防止内存泄漏)
5.内联函数;
inline函数在编译时被展开,在调用处将整个函数替换为代码块,省去了函数跳转的时间,提高了SD,减少函数调用的开销,虚函数是为了继承后对象能够准确的调用自己的函数,执行相应的动作。
主要的原因是:inline函数在编译时被展开,用函数体去替换函数,而virtual是在运行期间才能动态绑定的,这也决定了inline函数不可能为虚函数。(inline函数体现的是一种编译机制,而virtual体现的是一种动态运行机制
注意:派生类里的析构函数最好给成虚函数。否则派生类中如有空间的开辟那么有可能造成内存泄露
7.运算符重载可以写成虚函数但不建议用,如果硬要写成虚函数,可以看到写出的代码如下,
1 #include <iostream>
2 using namespace std;
3 class Base
4 {
5 public:
6 Base()
7 {
8 cout<<"Base::Base()"<<endl;
9 }
10 virtual ~Base()
11 {
12 cout<<"Base::~Base()"<<endl;
13 }
14 virtual Base & operator=(const Base &b)
15
16 {
17 return *this ;
18 }
19 };
20
21
22 class Derived :public Base
23 {
24 public :
25 Derived()
26 :_p(new int[10])
27 {
28 cout<<"Derived::Derived()"<<endl;
29 }
30 ~Derived()
31 {
32 if (_p)
33 delete[] _p;
34 cout<<"Derived::~Derived()"<<endl;
35 }
36 int * _p;
37 virtual Derived & operator=(const Derived &d)
38 {
39 return *this ;
40 }
41 };
可以看得因为参数列表的不同所以并不可以构成重写。也就是说写成虚函数是没有作用的(因为虚函数的作用是通过重写来实现的)。
换句话说必须是类的成员函数