I'm currently making a small "Game Engine". I was wondering if I should use smart pointers and which type I should use. or do I just use raw pointers for this GameObject class. every instance of GameObject have Component attached to it Transform, sprite etc. should I use smart pointers or just raw pointers. because I have never used smart pointers and I always get a bunch of errors when I try to. will it be fine to use raw pointers?
GameObject.h:
class Component;
class GameObject{
public:
GameObject();
virtual ~GameObject();
void addComponent(Component* component);
//return the first component of type T
template<typename T>
T* getComponent(){
for(auto component : components){
if(dynamic_cast<T*>(component)){
return dynamic_cast<T*>(component);
}
}
}
// return the component with the type T
template<typename T>
std::vector<T*> getComponents(){
std::vector<T*> components;
for(auto component : this->components){
if(dynamic_cast<T*>(component)){
components.push_back(dynamic_cast<T*>(component));
}
}
return components;
}
void removeComponent(Component* component);
std::vector<Component*> components;
};
//======================================================
class Component
{
private:
public:
Component();
virtual ~Component();
//the game object this component is attached to
GameObject* gameObject;
};
Thanks for reading.
CodePudding user response:
First things first. In general early failure is preferred over late failure. Failure after delivery is catastrophy. The most welcome form of failure is at compile-time. Good code tried to prevent runtime or logic errors by asserting errors at compile-time. So don't be frightened by compile errors. Next, you have to make a decision on lifespan of your objects and their ownership. The main problem with raw pointers is the ambiguity of implication; does a raw pointer imply:
- Just a reference
- An optional reference
- An owned resource
- An array beginning
- PIMPL
- ...
It's hard to tell by looking at the code using raw pointers, which asspect was intended. Confusions during coding lead to all sort of evil(including resource leak, double delete, use-after-free ...).
Smart pointers on the other hand, limited the use case of pointed-to-object to a very specific case(from above list or else). Moreover, smart pointers provide guarantees about lifespan of the object. Standard library provides a variety of classes (smart pointer or else) for different use-cases above.
If none of those classes are appropriate for a specific use case, I would rather define a wrapper to encapsulate the pointer and decorate its behavior.