Frage

Grundsätzlich habe ich eine reine virtuelle Klasse Basis und eine konkrete Klasse abgeleitet, die erbt von Base. I zuzuteilen dann ein Stück Speicher und behandle es als eine Anordnung von über einen einfachen Guss abgeleitet. Dann fülle ich das Array = verwenden. Schließlich habe ich Schleife durch das Array und versucht, die virtuelle Methode GetIndex zu nennen, die in der Base und definiert in Abgeleitet.

deklariert

Das Problem ist, dass ich eine Zugriffsverletzung Ausnahme am Ende immer versuchen, den Zeiger auf die VTable für Base zu lesen (in Visual Studio Debuggen, wird dies als __vfptr gezeigt, und es ist immer 0xbaadf00d).

Im Anschluss ist ein einfaches Beispiel für das Problem, das mir begegnet ist:

#include "stdafx.h"
#include "windows.h"

struct Base
{
    virtual int GetIndex() const = 0;
};

struct Derived : public Base
{
    int index;

    Derived()
    {
        static int test = 0;
        index = test++;
    }

    int GetIndex() const
    {
        return index;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    int count = 4;
    // Also fails with malloc
    Derived* pDerived = (Derived*)HeapAlloc(GetProcessHeap(), 0, sizeof(Derived) * count);

    for (int i = 0; i < count; i++)
    {
        Derived t;
        pDerived[i] = t;
    }

    // Should print 0 1 2 3
    for (int i = 0; i < count; i++)
    {
        Base& lc = pDerived[i];
        printf("%d\n", lc.GetIndex()); // FAIL!
    }
    return 0;
}

Dieses Verhalten tritt nur, wenn Sie den Speicher über HeapAlloc oder malloc zuzuordnen; wenn neue [] verwendet wird, funktioniert es gut. (Außerdem wird die cstor 4mal zuvor genannt, so dass der Ausgang 4 5 6 7 ist.)

War es hilfreich?

Lösung

Wenn Sie Speicher ohne new zuweisen Sie müssen immer den Konstruktor aufrufen manuell mit Platzierung neuer und die destructor mit x->~Derived();

Andere Tipps

Wenn Sie eine allocator neben C ++ 's Standard verwenden möchten, sollten Sie Ihre eigenen Operator neu anstatt zu versuchen, definieren zu erinnern, den Konstruktor jedes Mal anzurufen.

void *operator new[]( size_t block_size, HANDLE heap ) {
    return HeapAlloc( heap, 0, block_size );
}

...

Derived *pDerived = new( GetProcessHeap() ) Derived[ count ];

Details davon abhängen, ob Sie es wollen, dass der Standard-Weg, um Derived der Aufteilung und ob es wirklich braucht Parameter.

Sie müssen noch vorsichtig sein, wenn free() nicht den Speicher, den Sie bekam befreien kann. Dann wird die Standard delete wird nicht funktionieren, und Sie sollten entweder Derived::operator delete erstellen oder eigene Funktion schreiben, die object->~Derived() nennt.

ich denke, innerhalb der ersten Schleife für Sie ohne neu Objekt erstellen. Was bedeutet, dass der Kontext dieses Objekts ist Ihre for-Schleife. Diese Variable ist nicht mehr vorhanden, wenn Sie die for-Schleife zu beenden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top