zeboidlund
zeboidlund

Reputation: 10137

C++ Polymorphic Behavior: swapping derived pointer types

Observe the following code:

class A { public: virtual void Foo() = 0; int Bar; };

class B : public A { public: B( float X ); void Foo(); private: float X; };

class C : public A { public: C( float Y ); void Foo(); private: float Y; };

Now, in some function let's say I do this:

A*& pToA = pToDerived; // allocated as A* pToDerived = new B( ... );

pToA     = pToC; // allocated as A* pToC = new C( ... );

Is this valid? If so, will it cause a memory leak even though pToA is a reference to a pointer of pToDerived?

SSCS

Assume that Node has, say, 2 or more types which derive from it. This is a snippet from a linked list I'm implementing at the moment, which will likely require polymorphism in order to work properly, as it's not meant to be generic. newnode is the argument passed to an insert function.

    Node* iNode;

    for( iNode = mStart; iNode != mEnd; iNode = iNode->Next )
    {
        if ( iNode->Key == k ) // Replace current node with newnode
        {
            newnode->Next = iNode->Next;
            newnode->Prev = iNode->Prev;

            *iNode        = *newnode;

            delete newnode;

            return;         // We're done, so we quit.
        }
    }   

    // Node doesn't alreay exist, so we add it.

    Node*& uglyhack = mEnd;

    iNode->Next   = newnode;
    newnode->Prev = iNode;
    uglyhack      = newnode;

Upvotes: 0

Views: 337

Answers (2)

Vaughn Cato
Vaughn Cato

Reputation: 64308

This is the same as doing

pToDerived = pToC;

There's nothing inherently wrong with that. It will leak memory only if you never delete the objects, just like usual.

In your updated code, you could just do:

iNode->Next   = newnode;
newnode->Prev = iNode;
mEnd          = newnode;

and it would be the same.

Upvotes: 3

Billy ONeal
Billy ONeal

Reputation: 106530

Let's say you have the following:

// See http://codepad.org/8mG6YiLy
class A { public: virtual void Foo() = 0; int Bar; };

// Added definitions for these so that this would compile
class B : public A {
    public: B( float x ) : X(x) {}
    virtual void Foo() {} // Once virtual, always virtual
    private: float X;
};

class C : public A {
    public: C( float y ) : Y(y) {}
    virtual void Foo() {}
    private: float Y;
};

int main()
{
    A* pToDerived = new B(3.14);
    // pToDerived -> B

    A*& pToA = pToDerived;
    // pToDerived -> B
    // pToA IS pToDerived

    A* pToC = new C(2.718);
    // pToDerived -> B
    // pToC -> C
    // pToA IS pToDerived

    pToA = pToC;
    // pToDerived -> C
    // pToC -> C
    // pToA IS pToDerived
    // One object of type B no longer has pointers pointing to it
}

This code leaks two objects -- one of type B (which happens at the pToA = pToC statement) and one of type C (which happens when main returns). The "reference" in this case doesn't actually enter into much of play here. In C++, references are just aliases for some other object. You cannot "reseat" them. That is, once a reference references something, it can never reference anything else ever again.

In this case, when you created pToA, you created a reference to the pointer -- the pointer in this case being pToDerived. Making this reference has no effect on memory managment or responsability of some code to call delete in the right place whatsoever.

Upvotes: 2

Related Questions