首页 > 解决方案 > 在标头 C++ 中使用前向声明的模板类

问题描述

我有一个精灵类,它有一个模板化的数据成员。它拥有一个对象,该对象有一个指向这个专门的 sprite 模板类的指针。

该对象需要我的 sprite 类的前向声明,但由于 sprite 是一个模板类,我需要包含完整的标题。因此我得到了一个我无法弄清楚的循环依赖

精灵.h

#include "myclass.h"
 template<typename SpriteType, typename = typename std::enable_if_t<std::is_base_of_v<sf::Transformable, SpriteType> && std::is_base_of_v<sf::Drawable, SpriteType>>>
class Sprite {
public:
    SpriteType s;
    myclass<SpriteType>;
    Sprite() {
    }
    auto foo() {
        return s;
    }

private:

};

我的班级.h

#include "Sprite.h"

//a sprite of type T, is going to create a myclass<Sprite<T>>, a pointer of the Sprite<T> is held in myclass.

template<typename T>
class myclass
{
public:
    std::shared_ptr<Sprite<T>> ptr;
    myclass() {

    }
private:

};

我该如何解决这种循环依赖?

总而言之:

-Sprite 是一个模板类。

-Sprite 持有另一个类的对象。这个其他类拥有一个指向我的这个模板化精灵类的指针。

- 这给了我一个循环依赖,因为这两个类现在都是模板,并且需要将它们的实现写在它们的头文件中。

标签: c++

解决方案


模板的一大优点是打破了类型依赖。
你可以做这样的事情。为便于阅读而简化。

template<typename T>
class myclass
{
public:
    std::shared_ptr<T> ptr;
    myclass() {

    }
private:

};

template<typename SpriteType, typename = std::enable_if_t<std::is_base_of_v<base_class, SpriteType>>>
class Sprite {
public:
    SpriteType s;
    myclass<Sprite<SpriteType>> t;
    Sprite() {
    }
    auto foo() {
        return s;
    }

private:

};

这是众多选择之一。
另一种选择是使用接口。即不是模板的纯虚拟基类。

示例:我认为应该这样做。虽然开始变得难以理解。

class base_sprite
{
    public:
    virtual ~base_sprite(){};

    virtual int foo() = 0;
};

template<typename T>
class myclass
{
public:
    std::shared_ptr<base_sprite> ptr;

    myclass() : ptr(std::make_shared<T>())
    {

    };
};

template<typename SpriteType>
class Sprite : public base_sprite{
public:
    myclass<Sprite<SpriteType>> l;
    int foo() override {return 0;};
};

推荐阅读