在类 a 声明之前从类 a 继承类 b

Posted

技术标签:

【中文标题】在类 a 声明之前从类 a 继承类 b【英文标题】:Inherit class b from class a before class a declare 【发布时间】: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 只是一个使事情变得更容易并增加代码语义和可读性的包装器。抽象类是一个绝妙的主意。我想知道为什么我一开始没有考虑到它?!无论如何,谢谢你的评论。 【参考方案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】:

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

    更改设计依赖派生类所依赖的位置 在基类上 有派生类的指针或引用 在基类内部,派生类被前向声明 以类似的方式将基类设为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 的事实。

以上是关于在类 a 声明之前从类 a 继承类 b的主要内容,如果未能解决你的问题,请参考以下文章

php--在类中声明常量的关键字

5 友元类

友元的友元类

在类中声明装饰器

java的继承和实现中的“throw Exception”

如何在类中声明装饰器,以装饰已经装饰的继承方法?