本篇主要讨论两个问题:
1.成员函数中,虚函数是否有多态性?答案为:有;
2.构造和析构函数中,虚函数是否有多态性?答案为:无。
1.成员函数中,虚函数是否有多态性?
成员函数中的虚函数具有多态性。
以下代码中 void test() { foo(); }
普通成员函数中,调用的foo();
是否具有多态性(间接调用)?
p->test();
处设置断点,单步运行
#include <iostream>
class CParent
{
public:
virtual void foo() {
printf("void CParent::foo()\r\n");
}
//普通成员函数中,调用的foo具有多态性(间接调用,看虚表)
void test() {
foo();
}
};
class CMyclass :public CParent
{
public:
CMyclass() {}
virtual ~CMyclass() { }
virtual void foo() {
printf("void CMyclass::foo()\r\n");
}
};
int main(int argc, char* argv[])
{
//儿子对象的指针赋值给父亲
CParent* p = new CMyclass;//儿子的内容包含父亲所有内容,指针访问安全
p->test();
return 0;
}
运行结果:void test() { foo(); }
普通成员函数中,调用的foo()
是子类的函数,属于间接调用,具有多态
因此:普通成员函数中,调用的foo()
是具有多态性(间接调用,看虚表)
2.构造和析构函数中,虚函数是否有多态性?
构造和析构函数中,虚函数没有多态性
以下代码中CParent* p = new CMyclass;
先会调用子类CParent
构造函数,此时父类构造函数中的foo();
如果存在多态就会调用子类的函数,但是此时子类的还没有构造好,是无法调用的,因此调用的是父类的foo();
函数。
#include <iostream>
class CParent
{
public:
CParent() {
foo();
}
virtual ~CParent() {
}
virtual void foo() {
printf("void CParent::foo()\r\n");
}
void test() {
foo();
}
};
class CMyclass :public CParent
{
public:
CMyclass() {
foo();
}
virtual ~CMyclass() {
}
virtual void foo() {
printf("void CMyclass::foo()\r\n");
}
};
int main(int argc, char* argv[])
{
CParent* p = new CMyclass;
return 0;
}
运行结果:调用父类的函数,不属于间接调用,不具有多态性
因此在构造函数中调用虚函数,实际上是直接调用,所以没有多态
3.析构函数中调用普通成员函数,该普通成员函数中有虚函数的间接调用
在构造析构函数中调用普通成员函数,该普通成员函数中有虚函数的间接调用,由于进入构造时,会为对象赋值为当前类的虚表,所以没有多态。
如果将上述两种情况结合,构造函数中包含test()
函数,test()
函数中包含foo();
函数,
#include <iostream>
class CParent
{
public:
CParent() {
test();
}
virtual ~CParent() {
}
virtual void foo() {
printf("void CParent::foo()\r\n");
}
void test() {
foo();
}
};
class CMyclass :public CParent
{
public:
CMyclass() {
foo();
}
virtual ~CMyclass() {
}
virtual void foo() {
printf("void CMyclass::foo()\r\n");
}
};
int main(int argc, char* argv[])
{
CParent* p = new CMyclass;
return 0;
}
运行结果: CParent() { test();}
中调用父类中的foo();
,不存在多态
在析构函数中调用普通成员函数,该普通成员函数中有虚函数的间接调用,由于进入构造时,会为对象赋值为当前类的虚表,所以没有多态。
同理当test();
是在子类的构造函数中
class CMyclass :public CParent
{
public:
CMyclass() {
test();
}
virtual ~CMyclass() {
}
virtual void foo() {
printf("void CMyclass::foo()\r\n");
}
};
运行结果:调用子类的函数
4.学习视频地址:C++57个入门知识点_47 虚函数的多态性