C++ --类的默认成员函数是否可以被定义为虚函数
1.静态成员函数不能定义为虚函数
1.因为静态成员函数没有this指针,并且静态成员函数可以通过类名来访问。
2.又因为虚函数是放在对象的虚表里面的,同一个类中的所有对象虽然共用同一张虚表,但是类名无法找到虚表。
2.内联函数不能定义为虚函数
因为内联函数没有地址,而虚表里面存放的就是虚函数的地址。
3.构造函数不能定义为虚函数
1.因为虚函数是存放在对象的虚表里面,如果将构造函数定义为虚函数,则构造函数也必须存放在虚表里面,但是此时对象都还没有创建也就没有所谓的虚表。
2.不将构造函数定义为虚函数,对象模型如下:
3.如果将构造函数定义为虚函数:(直接会编译错误)
4.尽量不要将operator=定义为虚函数
虽然operator=不会构成重写(因为父类与子类的operator=虽然返回值可能会构成协变,但是他们的参数不相同),但是如果将其定义为虚函数不仅会引起歧义,而且会编译器做复杂的事情。
5.不要在构造函数和析构函数里面调用虚函数
1.因为在构造函数里面对象是不完整的,所以虚表有可能还没创建好,就有可能发生未定义的行为。
2.在析构函数里面对象的某些成员会被清理,对象也可能不完整,所以也可能会发生某些未定义的行为。(未定义的行为指我们无法预知的行为)
6.最好将基类的析构函数声明为虚函数
1.对于某些场景,不将基类的析构函数声明为虚函数没有问题,例如如下场景:(下面的代码没有问题)
class A
{
public:
A(int a = 0)
:_a(a)
{}
~A()
{
cout << "~A()" << endl;
}
public:
int _a;
};
class B : public A
{
public:
~B()
{
cout << "~A()" << endl;
}
public:
int _a;
};
int main()
{
A a;
B b;
a = b;
system("pause");
return 0;
}
但是对于下面场景就会有问题
class A
{
public:
A(int a = 0)
:_a(a)
{}
~A()
{
cout << "~A()" << endl;
}
public:
int _a;
};
class B : public A
{
public:
~B()
{
cout << "~B()" << endl;
}
public:
int _a;
};
int main()
{
A* p = new B;
delete p;
system("pause");
return 0;
}
2.可以发现new上一个子类对象时,只调用了父类的析构函数,没有调用子类的析构函数,如果子类的析构函数里面含有类似于free之类的函数,则会导致内存泄露,所以必须要想办法调用子类的析构函数。
3.通过了解知道父类与子类的析构函数同名,都被编译器修饰为的destructor.
如果将父类的析构函数定义为虚函数,则父类与子类的析构函数构成多态(因为子类的析构函数数继承了父类析构函数的特性为virtual),指向父类调用父类的析构函数,指向子类调用子类的析构函数。
例如:(将父类的析构函数定义为虚函数)
class A
{
public:
A(int a = 0)
:_a(a)
{}
virtual ~A()
{
cout << "~A()" << endl;
}
public:
int _a;
};
class B : public A
{
public:
~B()
{
cout << "~B()" << endl;
}
public:
int _a;
};
int main()
{
A* p = new B;
delete p;
system("pause");
return 0;
}
上一篇: 蓝牙开发那些事(4)——关于流控