将派生的虚拟覆盖强制转换为基础纯虚拟成员

时间:2016-07-28 13:25:36

标签: c++ inheritance virtual-functions pointer-to-member

我理解为什么你不能简单地将派生类成员函数指针强制转换为基类成员函数指针,如here所述。

但是,鉴于此片段:

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));

我想问一下是否可以修饰基本函数签名,以便编译器理解它是一个纯虚方法,并且它将在层次结构的某个地方实现(否则我无法构造类型{{1}的对象})?我理解为什么我不能用普通函数做这个,但是在纯虚函数的情况下恕我直言,编译器有保证它将被实现(如果没有完成我会得到关于类{{1}的错误不是关于演员表。)

3 个答案:

答案 0 :(得分:2)

无需操纵myMethod(int reso){scrl.pageScroll(View.FOCUS_UP); InputStream is = getResources().openRawResource(reso); BufferedReader br = new BufferedReader( new InputStreamReader(is)); String line; String entireFile = ""; try { while ((line = br.readLine()) != null) { // <--------- place // readLine() // inside loop entireFile += (line + "\n"); // <---------- add each // line to entireFile } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } secondyear.setText(entireFile); // <------- assign entireFile to // TextView if (slider.isOpened()) { slider.close(); }} 的类型。可以使用&derived::foo代替。

指向成员函数的指针尊重虚拟性。这个电话

&base::foo

实际上会调用base* pBase = new derived; auto pFoo = &base::foo; (pBase->*pFoo)(); ,就像简单的调用derived::foo一样。

答案 1 :(得分:0)

即使保证它已实现,它也可能使用仅在derived中声明的其他数据成员。一种可能的解决方案是使用函数指针并将this作为第一个参数传递(这也向您展示了为什么不能通过virtual执行此操作)。

答案 2 :(得分:0)

考虑以下钻石层次结构:

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 :: *的upcast的场景。应该调用哪个函数?编译器丢失了有关您希望调用的D1 :: foo,D2 :: foo或Derived :: foo中的哪些信息,因为该信息已被丢弃。为了避免这种歧义,不允许这样的上流。