Reputation: 27
I am trying to Polymorphism in c++ but when I try to call a function , the _vfptr is equal to 0xcccccccccccccccc .
Here is the Object class who contain virtals functions :
class Object
{
public:
Object()
{
Armageddon::Log::GetLogger()->trace("INSTANCIATE A NEW OBJECT");
};
virtual void InitVertexBuffer(ID3D11Device* device , ID3D11DeviceContext* device_contex ,Vertex v[], UINT VertexSize);
virtual void InitIndexBuffer(ID3D11Device* device, ID3D11DeviceContext* device_contex, DWORD indices[], UINT IndicesSize);
virtual void InitShaders(Microsoft::WRL::ComPtr <ID3D11Device>& device,std::wstring ShaderFloder, std::wstring VertexShader, std::wstring PixelShader, D3D11_INPUT_ELEMENT_DESC layout[], UINT SizeOfLayout);
virtual void InitConstantBuffer(ID3D11Device* device, ID3D11DeviceContext* device_contex);
virtual void BindVertexBuffer(ID3D11DeviceContext* device_contex);
virtual void BindIndexBuffer(ID3D11DeviceContext* device_contex);
virtual void BindShader(ID3D11DeviceContext* device_contex);
virtual void BindConstantBuffer(ID3D11DeviceContext* device_contex);
virtual void BindInputLayout(ID3D11DeviceContext* device_contex);
// virtual void Draw(ID3D11DeviceContext* device_contex) = 0;
virtual void Draw(ID3D11DeviceContext* device_contex);
virtual void DrawIndex(ID3D11DeviceContext* device_contex);
virtual void UpDateConstantBuffer(Camera* cam);
virtual void SetDrawFunction(const std::function<void(ID3D11DeviceContext* device_contex)>& callbackfunc) { DrawFunc = callbackfunc; };
virtual void SetName(const char* n) { this->name = n; };
const char* GetName() { return name; };
virtual Object* GetInstance()
{
return this;
};
bool CustomDraw = false;
int c = float(rand()) / float((RAND_MAX)) * 5.0f;
int b = float(rand()) / float((RAND_MAX)) * 5.0f;
float f = 0;
private:
VertexBuffer<Vertex> VertexBuffer;
IndexBuffer IndexBuffer;
VertexShader vertexShader;
PixelShader pixelShader;
ConstantBuffer<CB_VS_SHADER> ConstantBuffer;
// Object ID ?
const char* name = "default name";
};
Here is the other class :
class RenderModels : public Object
{
public:
RenderModels(Microsoft::WRL::ComPtr <ID3D11Device> device, Microsoft::WRL::ComPtr <ID3D11DeviceContext> device_context) : device(device), device_context(device_context)
{
Armageddon::Log::GetLogger()->trace("STATRING LAODING MODEL");
// SetName("Model");
Assimp::Importer imp;
const aiScene* model = imp.ReadFile("..\\TestApplication\\assets\\Models\\suzanne.obj", aiProcess_Triangulate |
aiProcess_JoinIdenticalVertices |
aiProcess_ConvertToLeftHanded |
aiProcess_GenNormals |
aiProcess_CalcTangentSpace);
//Assimp::Importer::GetErrorString();
// ProcessNode(model->mRootNode, model);
const aiMesh* pMesh = model->mMeshes[0];
Armageddon::Log::GetLogger()->trace(" LAODING MODEL : Enzo.obj");
for (unsigned int i = 0; i < pMesh->mNumVertices; i++)
{
v.push_back({ pMesh->mVertices[i].x,pMesh->mVertices[i].y ,pMesh->mVertices[i].z,1.0f,0.0f,1,1,0 });
}
InitVertexBuffer(device.Get(), device_context.Get(), v.data(),v.size());
//indices.reserve(pMesh->mNumFaces * 3);
for (unsigned int i = 0; i < pMesh->mNumFaces; i++)
{
aiFace face = pMesh->mFaces[i];
indices.push_back(face.mIndices[0]);
indices.push_back(face.mIndices[1]);
indices.push_back(face.mIndices[2]);
}
InitIndexBuffer(device.Get(), device_context.Get(),indices.data(), indices.size());
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{"POSITION",0,DXGI_FORMAT::DXGI_FORMAT_R32G32B32_FLOAT,0,0,D3D11_INPUT_CLASSIFICATION::D3D11_INPUT_PER_VERTEX_DATA,0},
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0},
};
InitShaders(device, L"..\\bin\\Debug-x64\\Armageddon\\", L"VertexShader.cso", L"PixelShader.cso", layout, ARRAYSIZE(layout));
InitConstantBuffer(device.Get(), device_context.Get());
CustomDraw = true;
Armageddon::Log::GetLogger()->error("FINISHED INIT RENDERMODEL");
};
void ProcessNode(aiNode* node, const aiScene* scene)
{
//Armageddon::Log::GetLogger()->trace("PROCESS NODE");
for (UINT i = 0; i < node->mNumMeshes; i++)
{
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
modelMeshes.push_back(ProcessMesh(mesh, scene));
}
for (UINT i = 0; i < node->mNumChildren; i++)
{
this->ProcessNode(node->mChildren[i], scene);
}
// Armageddon::Log::GetLogger()->trace("VECTOR ADRESS : {0}",modelMeshes.get_allocator().address(modelMeshes[0]));
};
Mesh ProcessMesh(aiMesh* mesh, const aiScene* scene)
{
std::vector<Vertex> v;
std::vector<DWORD> indices;
for (unsigned int i = 0; i < mesh->mNumVertices; i++)
{
if (mesh->mTextureCoords[0])
{
v.push_back({ mesh->mVertices[i].x,mesh->mVertices[i].y ,mesh->mVertices[i].z,mesh->mTextureCoords[0][i].x,mesh->mTextureCoords[0][i].y,1,1,0 });
}
}
for (unsigned int i = 0; i < mesh->mNumFaces; i++)
{
aiFace face = mesh->mFaces[i];
for (UINT j = 0; j < face.mNumIndices; j++)
{
indices.push_back(face.mIndices[j]);
}
}
return Mesh(device.Get(), device_context.Get(), v, indices);
};
/*Object* GetInstance() override
{
Armageddon::Log::GetLogger()->trace("INSTANCE");
return this;
};*/
/*virtual void Draw(ID3D11DeviceContext* device_contex)
{
Armageddon::Log::GetLogger()->trace("d");
};*/
std::vector<Mesh> GetMeshArray()
{
return this->modelMeshes;
};
private:
std::vector<Vertex> v;
std::vector<DWORD> indices;
std::vector<Mesh> modelMeshes;
Microsoft::WRL::ComPtr <ID3D11Device>& device;
Microsoft::WRL::ComPtr <ID3D11DeviceContext>& device_context;
};
And finally here is where I instanciate the Object :
class TestApp : public Armageddon::Application
{
public:
void OnUpdate() override;
void OnRender() override;
void ImGuiRender() override;
void Init() override;
void onMouseEvent(MouseEvent::MEventType);
void CameraControls();
TestApp()
{
}
~TestApp()
{
}
private:
ImVec2 CurrentWindowSize;
std::vector<Object*> o;
};
void TestApp::Init()
{
RenderModels m(Armageddon::Application::GetInstance()->GetWindow()->GetWindowGraphics()->GetComptrDevice(), Armageddon::Application::GetInstance()->GetWindow()->GetWindowGraphics()->GetComptrDeviceContext());
o.push_back(&m); // HERE IS WHERE I PUT THE RENDERMODEL OBJECT
Armageddon::Log::GetLogger()->trace("NAME : {0}", o[0]->GetName());
//Armageddon::Application::GetInstance()->GetWindow()->GetWindowGraphics()->GetVectorObjects()->at(0).get().GetInstance()->GetName(); //HERE EVERYTHING IS FINE NO PROBLEM WITH _VFPTR
a++;
}
This is the function where all fails:
void TestApp::OnRender()
{
for (UINT i = 0; i < o.size(); i++)
{
o[i]->Draw(Armageddon::Application::GetInstance()->GetWindow()->GetWindowGraphics()->Getdevicecontext()); // HERE ALL FAIL
}
}
I have used the Visual studio debugger to visualize the problem :
you can see in the second pictures the values of c and b changes and the _vfptr is null
Upvotes: 0
Views: 343
Reputation: 4243
The problem is in TestApp::Init
o.push_back(&m); // HERE IS WHERE I PUT THE RENDERMODEL OBJECT
You are pushing address of local object into the vector.
At the end of TestApp::Init() scope, m is destroyed and you're ending with a pointer to an invalid address.
You can try storing smart pointers (shared_ptr or unique_ptr). For example:
auto m = make_unique<RenderModels>(Armageddon::Application::GetInstance()->GetWindow()->GetWindowGraphics()->GetComptrDevice(), Armageddon::Application::GetInstance()->GetWindow()->GetWindowGraphics()->GetComptrDeviceContext())
or
auto m = make_shared<RenderModels>(Armageddon::Application::GetInstance()->GetWindow()->GetWindowGraphics()->GetComptrDevice(), Armageddon::Application::GetInstance()->GetWindow()->GetWindowGraphics()->GetComptrDeviceContext())
...
std::vector<std::unique_ptr<Object>> o; // or shared_ptr if you need shared ownersheep
and then
o.push_back(std::move(m)); // or o.push_back(m) if shared_ptr
Upvotes: 4