C ++ Polymorphic Behavior: замена производных типов указателей

Соблюдайте следующий код:

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?

SSCS

Предположим, что 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;

0

Решение

Допустим, у вас есть следующее:

// 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 в нужном месте вообще.

2

Другие решения

Это то же самое, что делать

pToDerived = pToC;

В этом нет ничего плохого. Это приведет к утечке памяти, только если вы никогда не удалите объекты, как обычно.

В своем обновленном коде вы можете просто сделать:

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

и было бы то же самое.

3

По вопросам рекламы [email protected]