【问题标题】:Inherit class b from class a before class a declare在类 a 声明之前从类 a 继承类 b
【发布时间】:2012-06-14 05:41:36
【问题描述】:

我想在实际声明 CDocument 之前从另一个名为 CDocument 的类继承一个名为 CSprite 的类,因为 CDocument 类的某些成员实际上是 CSprite。我希望它看起来不会令人困惑?这是我的代码:

class CSprite: public CDocument {}

class CDocument
{
public:
    CDocument();
    ~CDocument();

    CSprite * AddSprite(string Name);
    CSprite * GetSprite(string Name);
};

我收到“未定义的基类”错误。我想知道这可能根本不可能。是吗?我这样做的原因是增加我的代码可读性。每个文档都可以有许多精灵。精灵实际上是可以在其中包含其他精灵的文档。

【问题讨论】:

  • 文档与精灵有何不同?您是否考虑过为文档和精灵创建一个接口并从这个抽象基础继承?另外,为什么不对包含的精灵使用标准容器,例如矢量。
  • Sprites 与 Documents 完全相似。实际上我使用矢量容器进行存储。 CDocument 只是一个使事情变得更容易并增加代码语义和可读性的包装器。抽象类是一个绝妙的主意。我想知道为什么我一开始没有考虑到它?!无论如何,谢谢你的评论。

标签: c++ inheritance derived-class


【解决方案1】:

由于CDocument.AddSprite/GetSprite都返回一个CSprite指针,你可能只需要在文档中声明CSprite的存在即可。

//declare CSprite
class CSprite;

class CDocument
{
public:
    CDocument();
    ~CDocument();

    CSprite * AddSprite(string Name);
    CSprite * GetSprite(string Name);
};

您可以稍后在此文件或另一个文件中定义 CSprite,此时您应该能够继承 CDocument。虽然如果遇到更多问题,您可能需要重新设计对象结构。

//CSprite Class
class CSprite : public CDocument
{
    ...
};

【讨论】:

  • 正版!我主要是 Delphi 开发人员,这正是他们在 Delphi 中的做法。我不禁想知道这与使用模板有什么不同?
  • 当您想要编写可以与许多不同变量类型(ints double、MyObj 等)一起运行的代码时,模板用于更抽象的情况......变量类型不是的函数必须与操作相关,如果这有助于解释它。
【解决方案2】:

不能从不完整类型继承。
您可以通过以下不同方式解决问题:

  1. 更改设计依赖派生类所依赖的位置 在基类上
  2. 有派生类的指针或引用 在基类内部,派生类被前向声明
  3. 以类似的方式将基类设为template CRTP

【讨论】:

    【解决方案3】:

    模板基础:

    class Document;
    
    template<class Document=Document> class Sprite_t : public Document {  };
    typedef Sprite_t<Document> Sprite;
    
    class Document { /* etc. */};
    

    【讨论】:

    • +1 不错的技巧。但它改变了编程风格和界面:通过使 Sprite_t 成为模板,现在它的所有内部函数(本示例中没有,但通常情况并非如此)现在需要内联在标题中,不再需要在分开的可翻译来源中。这是否是一个问题,取决于上下文。
    • 模板成员函数可以单独定义。拥有可用的完整定义允许优化,但这不是必需的。
    • 好吧...这取决于您所说的“单独”:它们可以在类声明块之外定义,但不能在翻译单元之外定义。您不能将模板“编译”成 obj 并使其成为二进制库。这就是我所指出的。
    • 我想,如果你检查一下,你会发现这不是真的。
    • 认为?!?它不是。在这种情况下,你或我认为是无关紧要的。提供来源。
    【解决方案4】:

    不,这是不可能的。在定义派生类之前,需要完全了解基类。

    这看起来像是一个坏掉的设计。您可以通过先声明 CDocument 并更改签名来修复:

    class CDocument
    {
    public:
        CDocument();
        ~CDocument();
    
        CDocument * AddSprite(string Name);
        CDocument * GetSprite(string Name);
    };
    
    class CSprite: public CDocument {}
    

    【讨论】:

    • 这似乎不是一个好的解决方案。我的目标是提高代码的可读性。 AddSprite 返回 CDocument 会令人困惑。我想隐藏文档实际上是 Sprites 的事实。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-01
    • 2022-11-16
    • 2017-07-06
    • 2011-06-07
    • 1970-01-01
    • 2018-10-29
    • 2019-11-18
    相关资源
    最近更新 更多