函数指针和虚函数

发布于 2024-11-30 10:29:11 字数 91 浏览 0 评论 0原文

我想我的问题应该很愚蠢,但确实我从未见过被声明为虚拟的函数指针。这是有原因的吗?

编辑:

我应该说:它指向的函数是否有可能被指定为虚拟?

I guess my question should be silly but it is true that I have never seen a function pointer that is declared as virtual. Is there a reason for this?

Edit:

I should have said: Is it possible that the function it points to is specified as virtual?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你与昨日 2024-12-07 10:29:11

嗯,是的(也不是)。

普通函数指针不能指向非静态成员函数。它们只能指向独立的函数,这就是为什么对于普通函数指针来说,函数虚拟性的问题甚至不被考虑在内。

为了指向 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 调用 B::foo,而第二个将为对象 d 调用 D::foo,即使我们在两种情况下使用相同的指针值。这在许多应用中实际上是有意义的。

然而,在某些低级情况下,拥有一个硬绑定到特定版本的虚拟函数的指针会很有用。 时,如果有一个指针可以为对象 dB 子对象调用 B::foo ,那就太好了。

(d.*pfoo)();

也就是说,当我们这样做 需要能够指定我们是要提前(在初始化时)还是晚期(在调用时)绑定它。不幸的是,C++ 语言不提供这样的功能。

Well, yes (and no).

Ordinary function pointers cannot point to non-static member functions. They can only point to standalone functions, which is why for ordinary function pointers the matter of function virtuality does not even come into the picture.

In order to point to member functions in C++ you need a pointer of special kind: one that has pointer-to-member-function type. A pointer of this type can point to non-virtual member functions as well and to virtual member functions. There are no special steps to take if you want to point to virtual member function. For example

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`

However, when you make such pointer to point to a virtual member function, you have to keep in mind that it is does not really get tied to a specific version of that function in the class hierarchy. The decision about the specific function to call is made at the point of the call. For example

// 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`

In the above example we made out pointer pfoo to point to B::foo. Or did we? In reality the pointer is not hard-linked to B::foo specifically. These two calls

B b;
D d;

(b.*pfoo)();
(d.*pfoo)();

will call two different functions. The first one will call B::foo for object b, while the second one will call D::foo for object d, even though we used the same pointer value in both cases. This makes sense actually in many applications.

Yet, in some low-level situation it would be useful to have a pointer that is hard-tied to a specific version of virtual function. I.e. it would be nice to have a pointer that would call B::foo for B subobject of object d when we do

(d.*pfoo)();

To achieve that we need to be able to specify whether we want to bind it early (at the point of initialization) or late (at the point of the call). Unfortunately, C++ language provides no such functionality.

过去的过去 2024-12-07 10:29:11

函数指针只是指向函数的指针。它只是存储函数的地址,就像任何指向类型的指针存储类型的地址一样。

关键字virtual用于通过动态分派实现多态行为(基类和派生类的函数之间)。

鉴于上述两者明显不同,并且函数指针为虚拟的想法根本没有意义。

它指向的函数是否被指定为virtual?
正如我之前提到的,函数指针仅存储函数的地址。它只是一个类型。例如:

int *i = NULL;
void doSomething();
typedef void(*ptr)() = NULL;
ptr = &doSomething();

在上面的例子中:
iint * 的一种类型。同样,
ptr 是一种可以存储不带参数且不返回参数的函数地址的类型。

所以,是的,从根本上讲,您可以将函数指针指向的函数设为虚拟,就像通过在类中将特定函数声明为虚拟来将任何函数设为虚拟一样。

作为类型的函数指针可以指向具有该原型的任何函数,而将函数声明为虚拟意味着在特定函数上启用动态分派,正如您所见,两者并不相同。

A Function pointer is just a pointer to the function. It just stores address of an function just like any pointer to a type stores address of an type.

keyword virtual is used to implement polymorphic behavior(between functions of base class and derived class)through dynamic dispatch.

Given the above two are distinctly different and the idea of a function pointer to be virtual makes no sense at all.

whether the function it points to is specified as virtual ?
As I mentioned before an function pointer just stores address of an function. It is just an type. For eg:

int *i = NULL;
void doSomething();
typedef void(*ptr)() = NULL;
ptr = &doSomething();

In above example:
i is a type of int *. Similarly,
ptr is a type which can store address of an function which takes no parameter and returns no parameter.

So Yes, fundamentally, you can make the function to which a function pointer points as virtual, just like you would make any function virtual by declaring the particular function as virtual in the class.

The function pointer being a type can point to any function with that prototype, while declaring a function as virtual means having dynamic dispatch enabled on a particular function, as you see both are not the same.

幻梦 2024-12-07 10:29:11

虚拟性是成员函数的一个属性。如果你有一个指向虚拟成员函数的指针,那么将自动进行虚拟调用。常规函数不能是虚拟的,因此虚拟函数指针没有意义。在任何一种情况下,将函数指针设为虚拟都是没有意义的,因为它所指向的函数才是最重要的。

Virtuality is a property of member functions. If you have a pointer to a virtual member function then a virtual call will be made automatically. Regular functions can't be virtual, so a virtual function pointer makes no sense. In either case there's no point making a function pointer virtual as its the function being pointed to that counts.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文