LoginSignup
5
3

More than 5 years have passed since last update.

C++でUnityのGetComponentのようなものを実装してみた

Last updated at Posted at 2018-08-11

経緯

実行時型情報(RTTI)を使って何か書きたい

コンパイル環境

$ g++ --version
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.0.0 (clang-900.0.39.2)
Target: x86_64-apple-darwin16.7.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

コンパイル、リンク

g++ main.cpp -o main -std=c++11

コード


#include <cstdio>
#include <string>
#include <iostream>
#include <list>

class Object
{
public:
    Object() {}
    virtual ~Object() {}

    static void Destroy(Object* obj)
    {
        if (obj != nullptr)
            delete obj;
    }
};

class GameObject;
class Component : public Object
{
public:
    Component() {}
    virtual ~Component() {}

    virtual void Print()
    {
        std::cout << "I am Component!" << std::endl;
    }

    GameObject* gameobject;
};

class Transform : public Component
{
public:
    Transform() {}
    virtual ~Transform() {}

    virtual void Print()
    {
        std::cout << "I am Transform!" << std::endl;
    }
};

class Text : public Component
{
public:
    Text() : text("I am Text") {}
    virtual ~Text() {}

    std::string text;

    virtual void Print()
    {
        std::cout << text << std::endl;
    }
};

class GameObject : public Object
{
public:
    GameObject()
    {
    }
    virtual ~GameObject()
    {
        for (Component* component : componentList_)
        {
            if (component != nullptr)
                Destroy(component);
        }
    }

    template <class T, bool isExtended = std::is_base_of<Component, T>::value> T* AddComponent()
    {
        static_assert(isExtended, "AddComponent<> : T is not inherited from Component Class");
        T* component = new T();
        componentList_.push_back(component);
        return component;
    }

    template <class T> T* GetComponent()
    {
        T* component;

        for (Component* c : componentList_)
        {
            component = dynamic_cast<T*>(c);
            if (component != nullptr)
                return component;
        }
        return nullptr;
    }


    void PrintComponentList()
    {
        transform_.Print();
        for (Component* component : componentList_)
        {
            component->Print();
        }
    }

private:
    std::list<Component*>   componentList_;
    Transform               transform_;
};
template <> Transform* GameObject::GetComponent()
{
    return &transform_;
}


int main()
{
    GameObject gameObject;

    Text* text1 = gameObject.AddComponent<Text>();
    Text* i = gameObject.GetComponent<Text>();

    gameObject.PrintComponentList();

    rewind(stdin);
    getchar();
    return 0;
}
5
3
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3