1. 父类指针指向子类对象
- 虚函数的作用主要是实现了多态的机制。
- 可以用父类的指针指向其子类,然后通过父类的指针调用实际子类的成员函数。
- 仅仅可调用父类含有的虚函数,非父类函数不能调用
(1)普通虚函数调用
virtual 实现了父类的虚函数被子类的同名函数替换,实现了通过父类调用子类函数的功能。
class CFather
{
public:
CFather(void)
{
}
~CFather(void)
{
}
virtual void PrintOut(void)
{
cout << "父类PrintOut" << endl;
}
};
class CSon : public CFather
{
public:
CSon(void)
{
}
~CSon(void)
{
}
void PrintOut(void)
{
cout << "子类PrintOut" << endl;
}
};
int main()
{
CFather* father = new CSon();
father->PrintOut();//输出:子类PrintOut
cout << "Hello World!" << endl;
return 0;
}
(2)构造和析构函数的调用
构造析构 | 实例化方式 |
---|---|
先父类构造后子类构造 | 父类指针指向子类对象 等号右边new 子类 |
先父类构造后子类构造 | 子类指针指向子类对象 等号右边new 子类 |
先子类析构后父类析构 | 释放 子类指针指向子类对象 |
先子类析构后父类析构 | 释放 父类指针指向子类对象 (父类析构加virtual) |
只父类析构 | 释放 父类指针指向子类对象 (父类析构无virtual) |
a 父类析构函数为非虚函数
CFather(void)
{
cout << "父类构造" << endl;
}
~CFather(void)
{
cout << "父类析构~" << endl;
}
CSon(void)
{
cout << "子类构造" << endl;
}
~CSon(void)
{
cout << "子类析构~" << endl;
}
int main()
{
CFather* father = new CSon();
father->PrintOut();
delete father;
cout << "Hello World!" << endl;
return 0;
}
输出结果:
父类构造
子类构造
子类PrintOut
父类析构~
Hello World!
- 析构时由于父类的析构函数为非虚函数,所以未调用子类的析构函数。
- 若子类的构造函数存在动态内存分配,则会存在内存泄漏的问题。
b 父类析构函数为虚函数
virtual ~CFather(void)
{
cout << "父类析构~" << endl;
}
输出结果:
父类构造
子类构造
子类PrintOut
子类析构~
父类析构~
Hello World!
(3)父子类指针强制转换的安全性
a 父类指针强制转换为子类指针
one
class CFather
{
public:
CFather(void)
{
cout << "父类构造" << endl;
}
~CFather(void)
{
cout << "父类析构~" << endl;
}
void PrintOut(void)
{
cout << "父类PrintOut" << endl;
}
};
class CSon : public CFather
{
public:
CSon(void)
{
cout << "子类构造" << endl;
}
~CSon(void)
{
cout << "子类析构~" << endl;
}
void PrintOut(void)
{
cout << "子类PrintOut" << endl;
}
};
int main()
{
CFather *father = new CFather();
CSon* son = static_cast<CSon*>(father);
son->PrintOut();
delete son;
cout << "Hello World!" << endl;
return 0;
}
输出结果:
父类构造
子类PrintOut
子类析构~
父类析构~
Hello World!
将父类中与子类的同名函数定义为虚函数
将父类的析构函数定义为虚函数
结果反而不去调用子类的同名函数与析构函数
示例如下所示:
virtual ~CFather(void)
{
cout << "父类析构~" << endl;
}
virtual void PrintOut(void)
{
cout << "父类PrintOut" << endl;
}
输出结果:
父类构造
父类PrintOut
父类析构~
Hello World!
two
class CFather
{
public:
CFather(void)
{
cout << "父类构造" << endl;
}
virtual ~CFather(void)
{
cout << "父类析构~" << endl;
}
virtual void PrintOut(void)
{
cout << "父类PrintOut" << endl;
}
};
class CSon : public CFather
{
public:
CSon(void)
{
cout << "子类构造" << endl;
}
~CSon(void)
{
cout << "子类析构~" << endl;
}
void PrintOut(void)
{
cout << "子类PrintOut" << endl;
}
};
int main()
{
CFather *father = new CSon();
CSon* son = static_cast<CSon*>(father);
son->PrintOut();
delete son;
cout << "Hello World!" << endl;
return 0;
}
输出结果:
父类构造
子类构造
子类PrintOut
子类析构~
父类析构~
Hello World!
b 子类指针强制转换为父类指针
2. 子类指针指向父类对象
综上,对于C++继承个人建议
- 父类名* cptr = new 子类名()
- 定义父类中与子类同名的函数为虚函数
- 定义父类析构函数为虚函数
- 手动delete cptr
网友评论