关于c ++:通过强制转换来覆盖重写方法

Slice off overridden method by casting

我有一个公开继承自A的B类:

1
2
3
4
5
6
7
8
9
class A {
    private:
    virtual void method();
}

class B : public A {
    private:
    void method();
}

现在,我需要以某种方式调用B::method()中的原始A::method(),而不调用a的复制构造函数。a是在我试图扩展的库中定义的,因此我无法更改此代码(例如,使方法受保护)。有没有可能在B::method()中以某种方式抛出thisptr,然后切掉覆盖的method

我正在使用一个调用A::method()的外部接口。这个接口正确地调用了我被重写的B::method(),但我似乎不能在B::method()内进行接口调用,而不会产生堆栈溢出。


由于private方法不能被调用为Qualified,并且重写不能被撤消,因此在没有其他对象的情况下,您将无法调用private方法。强制转换对象没有任何效果,因为处理虚拟函数的方式是实际对象的一部分。

在过去,我曾主张使所有virtual函数(析构函数除外)private,但调用基类版本的需求实际上并不罕见。因此,virtual函数不应该是private函数,而应该是protected函数。当然,如果一个接口真的使它的virtual函数private的话,那么这个接口的用户就不能撤消设计错误。

鉴于支持恐怖黑客的答案(#define private protected获得了赞成票,我建议更依赖于添加的非virtual成员函数,而不是更改对象布局,并编辑头文件以添加合适的函数:

1
2
3
4
5
6
class A {
private:
        virtual void method();
protected:
    void call_method() { this->A::method(); }
};

这种变化具有更大的局部效应,也不可移植。但是,它仅仅依赖于对象布局,而不是通过添加非virtual(inline方法和访问说明符来更改。语言级别的警告不会受到影响。


在派生类中没有一致的方法来调用私有函数。

至少如果没有friend或成员模板,您可以专门使用自己的私有类型,在遵守法律的同时破坏意图。

  • 不过,还有#define private public黑客,可能对您的实现有效。但这是未定义的行为,所以不要抱怨它在任何地方都不起作用。可能的失效模式是连接误差,尽管理论上它可以变得任意奇异。

  • 更可靠的方法是添加一个非虚拟保护的内联转发器,尽管这意味着实际编辑头。

  • 此外,GCC还让-fno-access-control禁用所有访问检查:https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/c b_002b-dialect-options.html c b-dialect-options


    Turn off all access checking. This switch is mainly useful for working around bugs in the access control code.