【发布时间】:2016-07-28 13:25:36
【问题描述】:
我理解为什么不能像 here 解释的那样简单地将派生类成员函数指针转换为基类成员函数指针。
但是,鉴于这个 sn-p:
struct base
{
virtual void foo() = 0;
};
struct derived : base
{
void foo() override {};
};
struct invoker
{
typedef void(base::*target)();
invoker(base* b, target t)
{
(b->*t)();
}
};
template<typename B, typename D>
void (B::*cast(void (D::*method)()))()
{
return static_cast<void(B::*)()>(method);
}
derived d;
invoker bad(&d, &derived::foo); //C2664
invoker good(&d, cast<base>(&derived::foo));
我想问是否可以装饰基本函数签名,以便编译器理解它是一个纯虚方法,并且它将在层次结构的某个地方实现(否则我无法构造B类型的对象) ?我理解为什么我不能用普通函数做到这一点,但恕我直言,如果是纯虚函数,编译器保证它会被实现(如果没有完成,我会得到一个关于类 B 的错误不是关于演员)。
【问题讨论】:
-
不清楚你要什么样的装饰。如果你是 C++ 设计委员会的最高负责人,你会怎么做?不要担心一致性或正确性,只需显示您想要添加到 C++ 中的内容。如果你只是想告诉编译器
derived::foo存在于base中,你可以简单地写成&base::foo。 -
@n.m.我想避免做出明确的演员表:D 但它更像是“有什么我不知道的方式”类型的问题。
-
不,不做演员表。只需从
&base::foo开始。&derived::foo能做什么&base::foo不能? -
@n.m - 你真的让我大吃一惊。我试过了并进入了派生函数。你能解释一下 vtable 魔法发生在哪里吗?我正在传递一个指向
base::foo的指针,它是纯虚拟的。我通过函数指针调用它(这是否涉及 vtable 查找?)。谢谢:) -
指向成员函数的指针尊重虚拟性,就像普通的成员函数语法一样。通常这是通过在 ptr-to-mem 中的某处存储 vtable 偏移量来实现的。
标签: c++ inheritance virtual-functions pointer-to-member