1

好的,这是我想出的一些技巧,但我在现实世界的代码中使用它时遇到了一些问题。这是我想做的一个工作示例

class VirtualParent
{
public:
    virtual void printVal() = 0;
};

class Parent : public VirtualParent
{
public:
    virtual void printVal()
    {
        cout << "Val is: " << val << endl;
    }
    void SetVal(foo * v) { val = v; }
protected:
    foo* val;
};

class Child : public Parent
{
public:
    virtual void printVal()
    {
        cout << "From child, Val is: ";
        val->print();
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    Parent * p_ptr = new Child;
    foo * val = new foo;
    p_ptr->SetVal(val);
    p_ptr->printVal();

    for(int n = 0;n < 100;n++)
    {
        Parent * new_ptr = nullptr;

        //memcpy ( &new_ptr, &p_ptr, sizeof(Parent) );
        memcpy_s( &new_ptr, sizeof(p_ptr),&p_ptr, sizeof(p_ptr) );

        new_ptr->printVal();
    }

    return 0;
}

如果我使用 memcpy 或 memcpy_s,则此示例有效。这个想法是将用户派生类传递给一个函数,然后将创建几个副本,但由于我在编译时不知道派生类类型,所以我想到了这一点。正如我所说,这非常有效,我将它复制到我的引擎中,我想在其中使用它,并且我有一些内存问题不知从何而来,它们似乎与那个黑客有关。使用 memcpy_s 可以解决其中的一些问题。这是“好”的事情,还是有更好的方法?

这是“真实世界”的代码

_Lua::ScriptedEntity * newScript = EntityBase;//nullptr;
//assert(HeapValidate(GetProcessHeap(),0,nullptr));
//memcpy( &newScript, &EntityBase, sizeof(_Lua::ScriptedEntity) );
memcpy_s(&newScript, sizeof(EntityBase), &EntityBase, sizeof(EntityBase));

//assert(HeapValidate(GetProcessHeap(),0,nullptr));

string luaPath = transforms.next_sibling().next_sibling().first_attribute().as_string();

newScript->CompileFile(luaPath.c_str());

auto callback = [&](_Physics::Trigger* trigger,PxTriggerPair* pairs, PxU32 count) 
                            {
                                newScript->SelectScriptFunction("TriggerCallback");
                                newScript->AddParam(trigger->Id);

                                auto data = (_Physics::RayCastingStats*)pairs->otherShape->userData;

                                newScript->AddParam((PxU8)pairs->flags);
                                newScript->AddParam(data->ID);
                                newScript->AddParam((int)data->Type);

                                newScript->AddParam((int)count);

                                newScript->Go(1);

                                return;
                            };
((_Physics::Trigger*)EnginePTR->iPhysics->GetPhysicObject(StartingTriggerID))->InternalCallback = callback;

和班级

//class derived from LuaScript, implements a set of common use functions for AI scripts and similar. Used in the XLL parser.
    class ScriptedEntity : public LuaScript 
    {
    protected:
        static const int NumberOfFunctions = 11;
        std::array<function<int(LuaVirtualMachine& vm)>,NumberOfFunctions> FunctionsArray;
        int m_iMethodBase;
    public:
        ScriptedEntity(LuaVirtualMachine& vm) : LuaScript (vm)
        {
            InternalEntity = new Entity;

            m_iMethodBase = RegisterFunction("GetEntityPos");
            RegisterFunction("GetPlayerPos");
            RegisterFunction("Move");
            RegisterFunction("GetEntityLife");
            RegisterFunction("IsPlayerVisible");
            RegisterFunction("SetOrientationFromLookAt");
            RegisterFunction("RotateAxisUp");
            RegisterFunction("GetEntityOrientation");
            RegisterFunction("Idle");
            RegisterFunction("TeleportBehindPlayer");
            RegisterFunction("ApplyGravity");

            FunctionsArray[0]  = [this](LuaVirtualMachine& vm){ return this->GetEntityPos(vm); };
            FunctionsArray[1]  = [this](LuaVirtualMachine& vm){ return this->GetPlayerPos(vm); };
            FunctionsArray[2]  = [this](LuaVirtualMachine& vm){ return this->Move(vm); };
            FunctionsArray[3]  = [this](LuaVirtualMachine& vm){ return this->GetEntityLife(vm); };
            FunctionsArray[4]  = [this](LuaVirtualMachine& vm){ return this->IsPlayerVisible(vm); };
            FunctionsArray[5]  = [this](LuaVirtualMachine& vm){ return this->SetOrientationFromLookAt(vm); };
            FunctionsArray[6]  = [this](LuaVirtualMachine& vm){ return this->RotateAxisUp(vm); };
            FunctionsArray[7]  = [this](LuaVirtualMachine& vm){ return this->GetEntityOrientation(vm); };
            FunctionsArray[8]  = [this](LuaVirtualMachine& vm){ return this->Idle(vm); };
            FunctionsArray[9]  = [this](LuaVirtualMachine& vm){ return this->TeleportBehindPlayer(vm); };
            FunctionsArray[10] = [this](LuaVirtualMachine& vm){ return this->ApplyGravity(vm); };

            ViewRayCount = 16;
        }

        virtual int ScriptCalling (LuaVirtualMachine& vm, int iFunctionNumber)
        {
            if(iFunctionNumber - m_iMethodBase > NumberOfFunctions)
                return 0;
            else
                return FunctionsArray[iFunctionNumber - m_iMethodBase](vm);
            // The user might want to add functions to the script, and that's done by overloading this function. That's why it's virtual
        }

        // Functions
        //      Prototypes
        int GetEntityPos(LuaVirtualMachine& vm);
        int GetPlayerPos(LuaVirtualMachine& vm);
        int AttackPlayer(LuaVirtualMachine& vm);
        int Move(LuaVirtualMachine& vm);
        int GetEntityLife(LuaVirtualMachine& vm);
        int GetEntityRawDamage(LuaVirtualMachine& vm);
        int IsPlayerVisible(LuaVirtualMachine& vm);
        int SetOrientationFromLookAt(LuaVirtualMachine& vm);
        int RotateAxisUp(LuaVirtualMachine& vm);
        int GetEntityOrientation(LuaVirtualMachine& vm);
        int Idle(LuaVirtualMachine& vm);
        int TeleportBehindPlayer(LuaVirtualMachine& vm);
        int ApplyGravity(LuaVirtualMachine& vm);
        int ShootPlayer(LuaVirtualMachine& vm);

        //      Defined
        bool Update(float ElapsedTime)
        {
            SelectScriptFunction("Update");
            AddParam(ElapsedTime);

            Go(1);
            SelectScriptFunction("Clear"); // dummy function to clean the stack
            Go();
            return InternalEntity->Alive;
        }

        void HandleReturns (LuaVirtualMachine& vm, const char *strFunc)
        {
            if(string(strFunc) == "Update")
            {
                // frames returns an answer of the stack
                lua_State *state = (lua_State *) vm;
                InternalEntity->Alive = lua_tonumber(state,-1) != 0;
            }
        }

        // Vars
        Entity * InternalEntity;
        void * EnginePTR_voidptr;
        int PhysicID,VisualID,PlayerID;
        int ViewRayCount;
    };

此外,memcpy 发生在里面:

 HRESULT LoadSceneSimple(string Path,
                                        int StartingModelID,
                                        int StartingInstanceID,
                                        int StartingEmmitterID,
                                        int CameraID,
                                        int StartingTriggerID,
                                        int StartingMaterialID,
                                        int StartingPhysicsID,
                                        int ShaderID,
                                        void* engPtr,function<void(_X3D::BaseEffect* effect, _X3D::MaterialValues* matt,int ObjectID,int ShaderID)> MaterialCallback,
                                        string subfolder,
                                        _Lua::ScriptedEntity * EntityBase, string LuaSubfolder);
4

1 回答 1

7

你只是在复制一个指针。

即便如此,您也不能使用memcpy您尝试的方式,因为您需要知道关联的内存有多大(指针指向的内存),这可能因具体类而异。

做你想做的事情的一种方法是添加一个虚Parent* Parent::clone()函数,然后被Child* Child::clone().

然后你可以在不需要Parent* new_parent = p_ptr->clone()知道子类的情况下做类似的事情。

假定该clone()函数将负责new为正确/等效类型分配 () 堆内存。

于 2013-06-02T07:28:35.873 回答