我想我的问题应该是愚蠢的,但我确实从未见过声明为虚拟的函数指针。是否有一个原因?
编辑:
我应该说:它指向的功能是否可能被指定为虚拟?
答案 0 :(得分:5)
嗯,是的(和没有)。
普通函数指针不能指向非静态成员函数。它们只能指向独立的函数,这就是为什么对于普通的函数指针来说,函数虚拟性的问题甚至都没有出现在图片中。
为了指向C ++中的成员函数,您需要一个特殊类型的指针:一个具有指向成员函数类型的指针。这种类型的指针也可以指向非虚拟成员函数和虚拟成员函数。如果要指向虚拟成员函数,则无需执行任何特殊步骤。例如
struct B {
virtual void foo() {}
void bar() {}
};
...
B b;
void (B::*pfunc)(); // declare a pointer to a member function
pfunc = &B::foo; // make it point to `B::foo`
(b.*pfunc)(); // calls `B::foo` for object `b`
pfunc = &B::bar; // make it point to `B::bar`
(b.*pfunc)(); // calls `B::bar` for object `b`
但是,当您将此指针指向虚拟成员函数时,您必须记住,它实际上并未绑定到类层次结构中该函数的特定版本。关于要调用的特定功能的决定是在呼叫点进行的。例如
// given the above `B`
struct D : B {
virtual void foo() {}
};
...
void (B::*pfoo)(); // declare a pointer to a member function
pfoo = &B::foo; // and make it point to `B::foo`
在上面的示例中,我们指出pfoo
指针指向B::foo
。或者我们呢?实际上,指针并没有特别与B::foo
硬链接。这两个电话
B b;
D d;
(b.*pfoo)();
(d.*pfoo)();
将调用两个不同的函数。第一个将为对象B::foo
调用b
,而第二个将为对象D::foo
调用d
,即使我们在两种情况下都使用相同的指针值。这在许多应用程序中实际上是有意义的。
然而,在某些低级别的情况下,拥有一个与特定版本的虚函数紧密相连的指针会很有用。即当我们做
时,有一个指针可以为B::foo
对象B
的子对象调用d
会很好
(d.*pfoo)();
为了实现这一点,我们需要能够指定是否要提前(在初始化时)或延迟(在调用时)绑定它。不幸的是,C ++语言没有提供这样的功能。
答案 1 :(得分:2)
函数指针只是指向函数的指针。它只是存储函数的地址,就像任何指向type
存储类型地址的指针一样。
keyword virtual
用于通过动态调度实现多态行为(基类和派生类的函数之间)。
鉴于上面两个明显不同,函数指针为虚拟的想法完全没有意义。
它指向的功能是否指定为虚拟?
正如我之前提到的,函数指针只存储函数的地址。它只是一个type
。例如:
int *i = NULL;
void doSomething();
typedef void(*ptr)() = NULL;
ptr = &doSomething();
在上面的例子中:
i
是int *
的一种类型。同样,
ptr
是一种类型,它可以存储函数的地址,该函数不带参数并且不返回参数。
所以是的,从根本上说,你可以将函数指针指向的函数设置为虚函数,就像通过在类中将特定函数声明为虚函数来使任何函数虚拟一样。
作为类型的函数指针可以指向具有该原型的任何函数,而将函数声明为虚拟意味着在特定函数上启用动态调度,如您所见,两者都不相同。
答案 2 :(得分:1)
虚拟性是成员函数的属性。如果您有指向虚拟成员函数的指针,则会自动进行虚拟调用。常规函数不能是虚函数,因此虚函数指针没有意义。在任何一种情况下都没有必要将函数指针设为虚拟,因为它指向的函数是计数的。