How to define a C ++ base class at run time if a method has been overridden?

The following is an example of a method to determine if it has been overridden in a derived class. The error I get from MSVC implies that it’s just wrong to try to get a pointer to a “linked” member, but I don’t see a logical reason why this should be a problem (after all, it will be in this → virtual tables ). Is there any inadequate way to fix this code?

class MyClass
{
public:
    typedef void (MyClass::*MethodPtr)();  

    virtual void Method()
    {
        MethodPtr a = &MyClass::Method; // legal
        MethodPtr b = &Method;  // <<< error C2276: ‘&’ : illegal operation on bound member function expression

        if (a == b)     // this method has not been overridden?
            throw "Not overridden";
    }
};
+3
source share
3 answers

, , : . ( , "".)

struct A {
  virtual ~A() {} // abstract bases should have a virtual dtor
  virtual void f() = 0; // must be overridden
}

, :

void A::f() {}

: " , , ".

struct Base {
  void method() {
    do_method();
  }

private:
  virtual void do_method() {
    call_legacy_method_instead();
  }
};

struct Legacy : Base {
};

struct NonLegacy : Base {
private:
  virtual void do_method() {
    my_own_thing();
  }
};

, , . do_method , . (NonLegacy , , , .)

+4

. , .

#include<iostream>
#include<cstdio>
#include<stdint.h>

using namespace std;

class A {
public:
    virtual void hi(int i) {}
    virtual void an(int i) {}
};

class B : public A {
public:
    void hi(int i) {
        cout << i << " Hello World!" << endl;
    }
};

A B, B A .

, B - A

int function_address(void *obj, int n) {
    int *vptr = *(int **)&obj;
    uintptr_t vtbl = (uintptr_t)*vptr;

    // It should be 8 for 64-bit, 4 for 32-bit 
    for (int i=0; i<n; i++) vtbl+=8;

    uintptr_t p = (uintptr_t) vtbl;
    return *reinterpret_cast<int*>(p);
}

bool overridden(void *base, void* super, int n) {
    return (function_address(super, n) != function_address(base, n));
}

int n - , , vtable. , , .

int main() {
    A *a = new A();
    A *b = new B();

    for (int i=0; i<2; i++) {
        if (overridden(a, b, i)) {
            cout << "Function " << i << " is overridden" << endl;
        }
    }

    return 0;
}

Function 0 is overridden

EDIT: vtables , . , , - .

+1

. , , , , , assert( false ) .

0
source

Source: https://habr.com/ru/post/1723969/


All Articles