0

I have the following setup:

class CRpCat : 
    public CQueryDataBase,
    public IRpCat 
    {
public:
    CRpCat();
    virtual ~CRpCat();

// IRpCat
public:
    virtual HRESULT Initialize();

..... blah blah .......

class CQueryDataBase : public CQueryNotify
{
    // this has virtual functions, all concrete
    virtual void OnDataChange(ULONG nRow, DBREASON eReason);

..... blah blah .......

class CQueryNotify 
{
public:
    // abstract signatures
    virtual void OnDataChange(ULONG nRow, DBREASON eReason) = 0;

...... blah blah ..............

and finally

class IRpCat
{
public:
    virtual HRESULT Initialize() = 0;

So, I have a class thats deriving from 2 classes, and there are virtual functions everywhere. The classes derived from are NOT under one parent class -- this is NOT the diamond problem (although, probably, its related)

Here is the problem. When instantiating the class and making the Initialize() call, I end up in the OnDataChange() instead:

IRpCat *pCat = GetInstance()->GetRpCat();
pCat->Initialize();

Both Initialize() and OnDataChange() are the first functions in their respective vtable slots -- so I dont understand whats going on, but I get that the Initialize() call is happening through vtable[0] -- but unfortunately, I end up in the wrong vtable. On a hunch, I have tried the following:

By making the first line virtual, I end up in Initialize() correctly()

class CRpCat : 
       public virtual CQueryDataBase,
       public IRpCat 
       {

By making the second line virtual, I incorrectly end up in OnDataChange()

class CRpCat : 
       public CQueryDataBase,
       public virtual IRpCat 
       {

And by making both lines virtual, it throws an exception when making Initialize() call

class CRpCat : 
       public virtual CQueryDataBase,
       public virtual IRpCat 
       {

So, can someone please explain as to whats going on? (This is Visual Studio C++, by the way). It definitely has something to do with the way vtables are laid out. Thank you

alernerdev
  • 2,014
  • 3
  • 19
  • 35
  • Sounds like a bug with incorrect casting. Please provide more code/details. Definitely this should not happen. – valdo Nov 01 '17 at 18:09
  • Can you please try to create a [Minimal, **Complete**, and Verifiable Example](http://stackoverflow.com/help/mcve) to show us? – Some programmer dude Nov 01 '17 at 18:09

1 Answers1

1

Figured it out. The problem was the way the object was instantiated:

void * p = new CRpCat();
IRpCat * p2 = static_cast<IRpCat *>(p);
p2->Initialize();

Storing the pointer in "void *" first and then casting it, was "slicing" the pointer -- and therefore the weird results. Thank you all.

alernerdev
  • 2,014
  • 3
  • 19
  • 35