【发布时间】:2011-07-28 21:57:37
【问题描述】:
假设我有一些类链,其中每个类都派生自它之前的类。无论出于何种原因,他们都喜欢为某些成员函数使用相同的名称。有点像这样:
class C1 { public: void f() { cout<<"C1"; }; };
class C2 : public C1 { public: void f() { cout<<"C2"; }; };
class C3 : public C2 { public: void f() { cout<<"C3"; }; };
显然,如果我只是声明一些对象,然后从它们中调用函数 f ,都会调用与它们各自的对象类型相关联的函数:
C1 c1; c1.f(); // prints C1
C2 c2; c2.f(); // prints C2
C3 c3; c3.f(); // prints C3
现在,如果我声明一些指向对象的指针,然后从它们调用函数 f,所有将调用与它们各自的指针类型相关联的函数:
C1* p1 = &c1; p1->f(); // prints C1
C1* p2 = &c2; p2->f(); // prints C1
C1* p3 = &c3; p3->f(); // prints C1
C2* p4 = &c2; p4->f(); // prints C2
C2* p5 = &c3; p5->f(); // prints C2
C3* p6 = &c3; p6->f(); // prints C3
这一切都很棒。我要么调用与对象类型关联的函数,要么调用与指针类型关联的函数...
当然,我也可以将功能设为“虚拟”。然后,如果我从某个对象调用该函数,我的行为不会发生任何变化;但是,如果我从某个指针调用该函数,那么我将不仅仅调用该指针类型的函数,我实际上将调用该指针指向的对象类型的函数。到目前为止一切顺利。
我什至可以在继承链的中途对虚拟进行更改。假设我在 C2 类的函数 f 之前放置了一个 virtual。现在该函数已变为虚拟(即,当从指针调用时,它使用指向对象的类型而不是指针类型来解析函数调用),不仅适用于它自己的类,而且适用于所有未来的类来源于它。
我的问题是:一旦函数被声明为虚拟(在继承链中的某个点),它是否可以恢复为非虚拟(在继承链的更下方)?
澄清一下:当我说恢复到非虚拟行为时,我的意思是当我从指针调用函数时,它将使用指针的类型来解析函数调用(而不是指针的对象类型指向)。
【问题讨论】:
-
C1* p1 = &C1;等,你的意思一定是C1* p1 = &c1;(即你不尝试获取班级的地址)。 -
注意,您不能在链的中途使函数成为虚拟函数。您隐藏了原始功能并引入了一个新功能。您只会在该点以下获得多态行为;在它上面你会得到静态调度。
-
@Jimmy:当你说“reverted back”时,你期望什么行为?
-
@Dennis:这就是我所说的“在链的中途对虚拟进行更改”的意思——在引入关键字 virtual 之前,该函数将对所有类进行静态行为,并且然后使用 virtual 关键字对类以及从该类派生的所有类执行多态操作。这是可能的,是吗?
-
@larsmans:好电话,我对剪切和粘贴有点疯狂。固定。