Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Destructor Behavior

I had a question about C++ destructor behavior, more out of curiosity than anything else. I have the following classes:

Base.h

class BaseB;

class BaseA
{
    public:
        virtual int MethodA(BaseB *param1) = 0;
};

class BaseB
{
};

Imp.h

#include "Base.h"
#include <string>

class BImp;

class AImp : public BaseA
{
    public:
        AImp();
        virtual ~AImp();

    private:
        AImp(const AImp&);
        AImp& operator= (const AImp&);

    public:
        int MethodA(BaseB *param1) { return MethodA(reinterpret_cast<BImp *>(param1)); }

    private:
        int MethodA(BImp *param1);
};

class BImp : public BaseB
{
    public:
        BImp(std::string data1, std::string data2) : m_data1(data1), m_data2(data2) { }
        ~BImp();
        std::string m_data1;
        std::string m_data2;

    private:
        BImp();
        BImp(const BImp&);
        BImp& operator= (const BImp&);
};

Now, the issue is that with this code, everything works flawlessly. However, when I make the destructor for BImp virtual, on the call to AImp::MethodA, the class BImp seems to have its data (m_data1 and m_data2) uninitialized. I've checked and made sure the contained data is correct at construction time, so I was wondering what the reason behind this could be...

Cheers!

Edit: param1 was actually a reference to B in MethodA. Looks like I over-sanitized my real code a bit too much!

Edit2: Re-arranged the code a bit to show the two different files. Tested that this code compiles, a well. Sorry about that!

like image 524
sohum Avatar asked May 16 '26 15:05

sohum


2 Answers

If you are casting between related types as you do in this case, you should use static_cast or dynamic_cast, rather than reinterpret_cast, because the compiler may adjust the object pointer value while casting it to a more derived type. The result of reinterpret_cast is undefined in this case, because it just takes the pointer value and pretends it's another object without any regard for object layout.

like image 80
Alex B Avatar answered May 18 '26 04:05

Alex B


MethodA takes its parameters by value. This means a copy is passed (and the copy has to be destroyed). That's my best guess for why you might have a BImpl being destroyed that you didn't expect to be, but I don't see what the virtual or non-virtual nature of A's destructor could possibly have to do with it.

But this code can't compile - you use class B in declaring the virtual function in A, but B isn't defined until later. And I don't know what's going on with that cast - you can't reinterpret_cast class types. Perhaps if you work up a test case which demonstrates your issue, and post that?

like image 31
Steve Jessop Avatar answered May 18 '26 03:05

Steve Jessop



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!