It's plenty good actually - I guess that's what I was looking for, thanks.
There's an issue with this though:
class Branch {
std::vector<Branch*> childrens;
~Branch() {
for (//iterate over childrens) {
delete childBranch;
}
}
// everything else
}Well I guess it would work with a recursive function:
void destroyChildren()
{
for (auto iter = children.begin(); iter != children.end(); iter++)
{
childBranch->destroyChildren();
delete childBranch;
}
return;
}I hope I didn't think up some bs recursive function, cause I'm scared to test it in my code.
Though I guess now is the moment to ask - what works better(faster) - going through your structure with a recursive function, or having things stored in a vector and using brute force to solve the issues (for example I had a variant of the same program that did everything with loops rather than recursive functions (though it did pretty much the same now that I think about it))?
You don't need that recursion to destroy objects, it's recursive by default if you use the destructor. When you iterate over the childrens and call "delete childBranch", the destructor of each branch is called, which iterates over it's childrens and so on. You shouldn't have a method to destroy things, unless you need that functionality separated from the desctruction of the object itself. If you wanted to clear all the Tree you could have a "clear" method that destroys everything and keeps the "Tree" instance alive, but for cleaning purposes when exiting the program just call the destructors.
You are right. Till now whenever I was facing such situations I was always wondering whether to hardcode it or to do a check even if I know what I am going to get. I'd try to go for readability over needless optimizations from now on.
Always!
I actually wanted to dodge this issue by implementing branches.push_back() in the ctor of branches, but for that reason it would need to see the branches vector which is in Tree. And I've actually faced the problems with deleting you are talking about the previous time I coded something like this (it was not in c++ though ,and had a graphical visualization), I had to manage a few storage class instances, and I must say I was accessing a lot of null pointers, just because I forgot to remove an element here or there.
Practice recursion a little more, Trees are like the most common case where recursive functions are actually good, sometimes in college they make you write a recursive function for stuffs that could be easily done with a for loop, but working with trees gets a lot simpler with recursion.
On a side note (I'm not really sure whether I should make a new thread for this) speaking of nested classes and classes design. I cannot think of a way to code this without a friend declaration:
//Let's say we have a class Engine that can draw and load our meshes //However we shouldn't be able to create a mesh - that should be delegated to //the engine's function loadMesh, We should be able to do something like this. Engine myEngine; Mesh* myMesh = myEngine.loadMesh( "some_filename.3ds" ); myMesh.translate(1,3,5); myMesh.rotate( 30, 45, 0 ); //however this should be illegal: Mesh* mesh2 = new Mesh();
And here's what I think up of as a construction:
// ... includes #include <vector> class Mesh { friend class Engine; private: float transformationMatrix[4][4]; ID3D11Buffer* vertexBuffer; ID3D11Buffer* indexBuffer; public: void translate(const float vec[3]); void rotate(const float vec[3]); private: Mesh(); Mesh(const Mesh&); ~Mesh(); }; class Engine { private: std::vector<Mesh*> meshes; //... stuff public: //... stuff void loadMesh(std::string filename) { Mesh* temp = new Mesh; meshes.push_back(temp); } void drawMesh() { //draw the mesh by using the vertex and index buffers //and the transformation matrix } ~Engine() { //...free stuff for (auto iter = meshes.begin(); iter != meshes.end(); iter++) { delete *iter; } meshes.clear(); } };
Any way to do it without friend declarations?
Do you really need to prevent a Mesh being created manually? What's the problem with that? Most graphics libraries let you load a mesh or create it (directly or as a derived class).
Anyway, I'm not sure how to do that (never had the need) but as a first attempt you could make Mesh an abstract class, so "new Mesh();" wouldn't work, and have an inner class in Engine extending Mesh with the missing methods. It doesn't completelly hide the constructors tought, any class deriver from Mesh could be a concrete instantiable class just like the one inside Engine.