C++ 多态行为:交换派生的指针类型

C++ Polymorphic Behavior: swapping derived pointer types

本文关键字:派生 指针 类型 交换 多态 C++      更新时间:2023-10-16

观察以下代码:

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; };

现在,在某些函数中,假设我这样做:

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

这有效吗?如果是这样,即使pToA是对pToDerived指针的引用,也会导致内存泄漏吗?

南南合作

假设Node有 2 个或更多派生的类型。这是我目前正在实现的链表中的一个片段,它可能需要多态性才能正常工作,因为它不是通用的。 newnode是传递给插入函数的参数。

    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;

这与执行

相同
pToDerived = pToC;

这本身并没有什么错。 仅当您像往常一样从不删除对象时,它才会泄漏内存。

在更新的代码中,您可以执行以下操作:

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

这将是相同的。

假设您有以下内容:

// 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
}

此代码泄漏两个对象 - 一个是 B 类型(发生在 pToA = pToC 语句中),另一个是 C 类型(在 main 返回时发生)。在这种情况下,"参考"实际上并没有在这里发挥作用。在C++中,引用只是其他某个对象的别名。您无法"重新拔插"它们。也就是说,一旦引用引用了某些内容,它就再也不能引用其他任何内容。

在本例中,当您创建 pToA 时,您创建了对指针的引用 - 在本例中指针pToDerived 。进行此引用不会影响内存管理或某些代码在正确位置调用delete的责任。