首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >仅通过继承其他类来定义类型

仅通过继承其他类来定义类型
EN

Stack Overflow用户
提问于 2013-10-18 01:13:41
回答 2查看 372关注 0票数 2

我正在用SFML实现一个可视化的树。它包含两个重要的绘图类:sf::Drawablesf::Transformable。如果这些都捆绑在一起会很好,但它们不是。许多对象都继承了这两者,即:

代码语言:javascript
复制
class SFML_GRAPHICS_API Text : public Drawable, public Transformable

class SFML_GRAPHICS_API Sprite : public Drawable, public Transformable

class SFML_GRAPHICS_API Shape : public Drawable, public Transformable

对于我的可视化树,我有一个从Drawable和Transformable继承的SceneNode类,一个绘图函数将调用一个私有onDraw本身,然后调用它的子类。然而,许多SFML本机类,比如sf::Text,都有一个私有的绘图函数。因此,我不能创建像这样的类

代码语言:javascript
复制
class Text: public sf::Text, public SceneNode

然后将其放入可视化树中。对于这些原生类,我不需要它们有绘制子类,我只希望能够将它们作为叶子节点添加到可视化树中。问题的症结在于可视化树的每个成员都需要从sf::Drawablesf::Tranformable继承。我需要能够定义一个从这两者继承的类型。如果我定义了虚拟类

代码语言:javascript
复制
class LeafNode: public sf::Drawable, public sf::Tranformable { }

它似乎定义了我想要的类型。然后,SceneNode将包含std::vector<LeafNode*> m_children。在绘制这些子项时,我将对每个项进行动态强制转换,以查看它是否是一个绘制,然后调用一个SceneNode函数,以便SceneNode绘制它的子项。

但是,由于类型不兼容,以下代码无法编译:

代码语言:javascript
复制
LeafNode * node = new sf::Text("PLAY", font, 20);

理想情况下,我希望定义如下内容

代码语言:javascript
复制
std::vector<sf::Drawable, sf::Transformable*> m_children 

其中,这种虚构的语法意味着每个元素都必须从sf::Drawablesf::Transformable派生。这个是可能的吗?

EN

回答 2

Stack Overflow用户

发布于 2013-10-18 03:31:37

然而,许多SFML本机类,如sf::Text,都有一个私有的绘制函数

事实并非如此。由于sf::Drawable::draw函数是受保护的,因此sf::Textdraw方法也是如此。这是C++的复杂规则之一。

所以,我不能创建一个像这样的类

类Text:公共sf::Text,公共SceneNode

如果这样做,层次结构中就会有两个sf::Drawablesf::Transformable基类,一个来自sf::Text,另一个来自SceneNode。那可不太好。

当绘制这些子项时,我将对每个项进行动态强制转换,以查看它是否是SceneNode,然后调用一个

函数,以便SceneNode绘制它的子项。

我不推荐这样的设计。使用dynamic_cast通常是你的软件设计不是很好的标志。(我不想在这个话题上离题太多,谷歌关于这个话题。)

但让我们来回答你的基本问题:

,其中组合语法意味着每个元素都必须派生自sf::Drawable和sf::Transformable。这个是可能的吗?

不是的。但不管怎样,你可以做一些更简单的事情。

与其让Text同时继承sf::TextSceneNode,不如将您的类定义为包装器。它可以像下面这样简单:

代码语言:javascript
复制
class Text : public SceneNode {
    sf::Text m_text;
public:
    sf::Text& get() { return m_text; }

    // Override SceneNode drawing method:
    virtual void onDraw(RenderTarget& target) const
        // Draw m_text:
        target.draw(m_text);
    }
};

不过,这个快速包装器有两个缺陷。a)它不使用SceneNode的可转换部分。b)由于使用get()打破了封装,因此有两个可由用户修改的可转换包:来自SceneNode的包和来自sf::Text的包。

对于a),当你修复b)时,修复应该是简单的。要修复b),您必须使包装器稍微复杂一点:不是使用这个丑陋的get(),而是编写方法来设置底层sf::Text的属性,这些属性没有链接到sf::Transformable,例如setColor

票数 0
EN

Stack Overflow用户

发布于 2013-10-18 04:05:25

在不了解SMFL (它可能提供更好的解决方案)的情况下,我认为您可以实现此向量。您只需要定义自己的指针包装器,它只接受指向从多种类型继承的对象的指针:

代码语言:javascript
复制
template <class T1, class T2>
struct special_pointer_wrapper
{
    T1* t1;
    T2* t2;
    template<class T>
    special_pointer_wrapper(T* p)
        : t1(dynamic_cast<T1*>(p))
        , t2(dynamic_cast<T2*>(p))
    {
       if ((p1==0) || (p2==0))
           throw "Error";
    }

    getT1 T1* () const { return t1; }
    getT2 T2* () const { return t2; }
};

这个类接受任何指针,并确保它指向的类型是从T1和T2派生的(即使它们看起来完全无关)。如果它不是派生对象,则抛出。通过函数getT1()getT2(),您可以访问指向这两个基类的指针。

请注意,由于dynamic_cast的原因,构造可能会很慢,但类型的提取是O(1)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19433139

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档