原文:当“友元”遇到“虚函数” http://student.csdn.net/space.php?uid=112600&do=blog&id=17266
要理解有时候,人们其实就是在故意做这种事,最典型的做法,就是通过非虚函数调用虚函数:
- class B
- {
- public:
- void Action()
- {
- this->DoAction();
- }
- private:
- virtual void DoAction() = 0; //一个私有的纯虚函数
- // friend class A;
- };
任何一个合格的C++程序员,都应该学会这种作法。DoAction是一个纯虚函数,这里我们更决绝一点,干脆让它是私有的,这就是逼着派生类自己去实现一个完全自我的DoAction(),假设有个class D : public B,并且听话地实现了DoAction。具体D的定义,为节省点篇幅,不写了。
注意到第11行的注释, class A 现在已经不是 B 的友员了,但不要紧,我们只是想在新版的类A中,调用Action函数,而它是public的,所以这里不需要友元来搅和。
- class A
- {
- void test()
- {
- B* pb = new D; //pb 实际指向一个D对象。
- pb->Action(); // Action 是 公开的,所以可以调用
- }
- };
pb 调用了非虚的B::Action函数,但在Action内调用了虚函数DoAction,再由于pb实际指向的是D对象,所以最终调用的是D::DoAction()——这了无新意对不对?只要学过一点C++的多态,都会懂这一点。没错,它太司空见惯了,基本上所有C++程序员每天都会在写类似的代码——这就是我想说的,有时候,看起来在调用基类的代码,但实际上在调用派生类的代码。假设我们修改了语法规则,逼着虚函数在遇上友元之后失效,那就是逼着程序员不去用friend,去将更多本来应该是private的成员,用各种该法写成public的。