Ошибка связывания при использовании нескольких базовых классов - PullRequest
0 голосов
/ 22 января 2012

У меня есть два базовых класса;«MemoryManagedObject» и «Gameobject».Идея состоит в том, чтобы мои собственные классы наследовали от «Gameobject», который наследуется от «MemoryManagedObject».

#ifndef _GAME_OBJECT_H
#define _GAME_OBJECT_H

#include "MemoryManagedObject.h"

class GameObject : public MemoryManagedObject
{
public:
    GameObject() { }
    GameObject(bool UseMemPool): MemoryManagedObject(UseMemPool) { }
    virtual ~GameObject() { }

    long GetGameObjectID();

protected:
    long mGameObjectID;
};

inline long GameObject::GetGameObjectID()
{
    return mGameObjectID;
}

#endif


#ifndef _MEMORY_MANAGED_OBJECT_H
#define _MEMORY_MANAGED_OBJECT_H

#include <new>

class MemoryManagedObject
{
public:
    MemoryManagedObject();
    MemoryManagedObject(bool UseMemPool);
    virtual ~MemoryManagedObject() { DecreaseRefCount(); }

    bool IsAllocatedWithMemPool();
    void* operator new(size_t size);
    void* operator new(size_t size, bool UseMemPool);
    void operator delete(void* obj);
    long GetRefCount();

private:
    void IncreaseRefCount();
    void DecreaseRefCount();

    long mRefCount;
    bool mAllocatedWithMemPool;
};

#endif

Однако мой компилятор (android-ndk, gcc 4.4.1 afaik) выдает мне «Undefined Reference»ошибки компоновщика в функциях: ~ MemoryManagedObject и ~ GameObject: неопределенная ссылка на MemoryManagedObject :: delete (void * obj) и MemoryManagedObject :: DecreaseRefCount

Почему это так?Я написал все методы в .cpp файлах, которые включены в компиляцию;Я полагаю, что что-то не так с тем, как я объявляю виртуальные деструкторы, но я не знаю почему.

РЕДАКТИРОВАТЬ: публикация testclass и файлов cpp:

TestClass1.h

#ifndef _TEST_CLASS_1_H
#define _TEST_CLASS_1_H

#include "GameObject.h"

class TestClass1 : public GameObject
{
public:
    TestClass1();
    TestClass1(bool UseMemPool);
    ~TestClass1();

    void TestMe();
};

TestClass1.cpp

#include "TestClass1.h"

TestClass1::TestClass1()
{

}

TestClass1::TestClass1(bool UseMemPool): GameObject(UseMemPool)
{

}

TestClass1::~TestClass1()
{

}

void TestClass1::TestMe()
{

}


#endif

GameObject.cpp

#include "GameObject.h"

GameObject::GameObject()
{

}

GameObject::GameObject(bool UseMemPool): MemoryManagedObject(UseMemPool)
{

}

GameObject::~GameObject()
{

MemoryManagedObject.cpp

#include "MemoryManagedObject.h"
#include "Engine.h"

#include <stdint.h>


MemoryManagedObject::MemoryManagedObject()
{
    mAllocatedWithMemPool = false;
    IncreaseRefCount();
}

MemoryManagedObject::MemoryManagedObject(bool UseMemPool)
{
    mAllocatedWithMemPool = UseMemPool;
    IncreaseRefCount();
}

MemoryManagedObject::~MemoryManagedObject()
{
    DecreaseRefCount();
}

long MemoryManagedObject::GetRefCount()
{
    return mRefCount;
}

void MemoryManagedObject::IncreaseRefCount()
{
    mRefCount++;
}

void MemoryManagedObject::DecreaseRefCount()
{
    mRefCount--;
    if (mRefCount <= 0)
    {
        delete this;
    }
}

bool MemoryManagedObject::IsAllocatedWithMemPool()
{
    return mAllocatedWithMemPool;
}

void* MemoryManagedObject::operator new(size_t size)
{
    Engine* engine = Engine::GetEngine();
    void* alloc;

    alloc = engine->GetMemoryManager()->Allocate(size);

    return alloc;
}

void* MemoryManagedObject::operator new(size_t size, bool UseMemPool)
{
    Engine* engine = Engine::GetEngine();
    void* alloc;

    alloc = engine->GetMemoryManager()->Allocate(size, UseMemPool);

    return alloc;
}


void MemoryManagedObject::operator delete(void* obj)
{
    Engine* engine = Engine::GetEngine();
    MemoryManagedObject* memObj = (MemoryManagedObject*)obj;

    engine->GetMemoryManager()->Deallocate(obj,memObj->IsAllocatedWithMemPool());
}

}

1 Ответ

1 голос
/ 22 января 2012

Вы пишете свои виртуальные деструкторы встроенными, что обычно заставляет их испускаться в каждой единице компиляции, как слабые символы.Кроме того, поскольку первая (и единственная) виртуальная функция в ваших классах - это деструктор, это будет ключевая функция, с которой будет генерироваться виртуальная таблица.

Я предполагаю, что эти две вещи взаимодействуютплохо, в результате чего встроенные деструкторы не будут включены в окончательную ссылку.

В любом случае, решение состоит в том, чтобы переместить определение ваших виртуальных деструкторов вне строки в файл cpp.Если вы не объявите экземпляры ваших объектов в стеке, дескрипторы никогда не будут вызываться, кроме как через vtable.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...