将派生的虚拟重写强制转换为基纯虚拟成员
Cast derived virtual override to base pure virtual member
我理解为什么不能像这里解释的那样,简单地将派生类成员函数指针强制转换为基类成员函数指针。
但是,给定这个片段:
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
类型的对象)?我理解为什么我不能用普通函数做到这一点,但IMHO在纯虚拟函数的情况下,编译器有保证它会被实现(如果没有实现,我会得到关于类B
的错误,而不是关于强制转换的错误)。
不需要操作&derived::foo
的类型。可以直接使用&base::foo
。
指向成员函数的指针尊重虚拟性。此呼叫
base* pBase = new derived;
auto pFoo = &base::foo;
(pBase->*pFoo)();
将实际调用derived::foo
,就像简单调用pBase->foo()
一样。
即使有实现的保证,它也可能使用仅在derived
中声明的其他数据成员。一个可能的解决方案是使用函数指针并将this
作为第一个参数传递(这也说明了为什么不能通过virtual
执行此操作)。
考虑以下菱形层次结构:
struct base {
virtual void foo() = 0;
};
struct D1 : public virtual base {
virtual void foo() override;
};
struct D2 : public virtual base {
virtual void foo() override;
};
struct Derived : public virtual D1, D2 {
virtual void foo() final;
};
现在考虑一个场景,其中允许从Derived::*向base::*进行上转换。应该调用哪个函数?编译器将丢失有关您希望调用D1::foo、D2::foo或Derived::foo中哪一个的信息,因为这些信息已被丢弃。为了避免这种模棱两可的情况,不允许进行这种升级。
相关文章:
- 虚拟成员函数的定义是否强制在同一转换单元中动态初始化静态数据成员?
- 钻石继承虚拟成员铸造与指针
- 将函数强制转换为成员函数
- 如果我必须覆盖非虚拟成员函数怎么办
- c++\CLI dll包装器,用于调用c++类中的虚拟成员
- 非虚拟成员函数是否可以使用模板参数?
- 如何将已实现的虚拟成员函数作为参数传递
- 调用虚拟成员类的方法
- 睡眠影响 std::thread 调用哪个虚拟成员函数?
- 向下转换指向成员函数的指针.这是合法用法吗?
- 我可以使用std :: bind将指针转换为成员函数的指针转换为函数的指针
- GTEST:嘲笑非虚拟成员函数
- 使SDL称为纯虚拟成员作为事件回调
- 在C中使用具有虚拟成员(即非POD)的C++结构
- C++隐式将平凡可构造的结构转换为成员
- 虚拟和非虚拟成员函数的调用方式有什么区别?
- 默认情况下是虚拟成员函数
- 是否可以在不重写派生类中记录虚拟成员?
- 如何使用基类指针调用派生类非虚拟成员函数,而无需类型转换和使用多态性
- 将派生的虚拟重写强制转换为基纯虚拟成员