Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Slice off overridden method by casting

I have a class B that inherits publicly from A:

class A {
    private:
    virtual void method();
}

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

Now, I need to somehow call the original A::method() within B::method(), without invoking the copy constructor for A.
A is defined in a library I'm trying to extend, so I can't change this code (make method protected for example). Is it possible to somehow cast the this ptr within B::method() and slice off the overridden method?

I'm using an external interface that calls A::method(). This interface correctly calls my overridden B::method(), but I can't seem to make the interface call within B::method() not generate a stack overflow.

like image 270
BarrensZeppelin Avatar asked Dec 17 '14 18:12

BarrensZeppelin


2 Answers

Since private method can't be called qualified and the override can't be undo you won't be able to call the private method without another object. Casting the object won't have any effect because the way virtual functions are handled is part of the actual object.

In the past I had advocated making all virtual functions (other than the destructor) private but the need to call the base class version is actually not that uncommon. Thus, virtual functions should not be private but rather protected. Of course, if an interface actually makes its virtual functions private that design mistake can't be undone by the user of this interface.

Seeing that answers advocating horrible hacks (#define private protected) get upvotes, I'd recommend to rather rely on non-virtual member functions being added not changing the object layout and edit the header file to add a suitable function:

class A {
private:
        virtual void method();
protected:
    void call_method() { this->A::method(); }
};

This change has a much more local effect and is also just not portable. However, it merely relies on the object layout not being changed by adding a non-virtual (inline) method and an access specifier. No warnings at the language level or so would be affected.

like image 79
Dietmar Kühl Avatar answered Nov 15 '22 08:11

Dietmar Kühl


There is no conforming way to call the private function in the derived class.

At least if there is no friend or member-template you can specialize with your own private type to subvert the intent while obeying the letter of the law.

  1. Still, there is the #define private public-hack, which might work on your implementation.
    It's Undefined Behavior though, so don't complain that it does not work everywhere. Probable failure-mode is linking-error, though it can in theory get arbitrarily bizarre.

  2. Far more reliable would be adding a non-virtual protected inline-forwarder, though that means actually editing the header.

  3. Also, gcc has -fno-access-control to disable all access-checking: https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/C_002b_002b-Dialect-Options.html#C_002b_002b-Dialect-Options

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

like image 29
Deduplicator Avatar answered Nov 15 '22 08:11

Deduplicator