C ++:如何使用尚未定义的类型?

时间:2010-06-03 19:01:21

标签: c++ header declaration forward-declaration

C ++要求在使用之前定义所有类型,这使得以正确的顺序包含头文件很重要。精细。但是我的情况呢:

Bunny.h

   class Bunny
   {
       ...
   private:
       Reference<Bunny> parent;
   }

编译器抱怨,因为技术上Bunny尚未完全定义在我自己的类定义中使用它。因为我做了一些愚蠢的事情(无关< / em>的)。

除了重写我的模板类Reference所以它需要一个指针类型(在这种情况下我可以使用Bunny的前向声明),我不知道如何解决这个问题。

有什么建议吗?

编辑:我的Reference类(XObject是数据模式对象的基类):

template <class T = XObject> class Reference
{
public:
    Reference() : m_ptr (NULL) {}
    Reference(T* p)
    {
        m_ptr = p;
        if (p != NULL) ((XObject*)p)->ref();
    }
    ~Reference()
    {
        if (m_ptr)
        {
            ((XObject*)m_ptr)->deref();
        }
    }

    // ... assignment, comparison, etc.

private:
    T* m_ptr;
}; 

编辑:这很好用,问题还不错。非常感谢你的帮助!

3 个答案:

答案 0 :(得分:3)

您的问题的答案取决于参考&lt;&gt;好像。如果它有一个Bunny类型的实例变量,那么当然它将无法工作(如何,你有一个永远不会结束的递归定义)。如果它只有引用和指针,那么它应该工作正常。模板实例化中的Bunny类型不会干扰它。

编辑(发布参考&lt;&gt;代码编辑):

我似乎无法重现你的问题。我重新实现了代码,就像你正在做的那样,但它对我编译很好:

struct base {
  void fun() {}
};
template < typename T >
struct temp
{
  T * t;

  void f() { ((base*)t)->fun(); }
};

struct test
{
  temp<test> t;

};

int main()
{
  test t;
  t.t.f();
}

这显然是无效的代码,因为你将得到未定义的结果,但它确实编译。这里的问题主要是从类型test *到类型base *的重新解释。如果测试确实从基础继承,那么甚至不需要演员。像这样的代码将不会按预期运行,但它应该编译得很好。我有一个建议是失去所有的C风格演员。这不会解决你遇到的问题,无论它是什么......它必须在你没有粘贴的代码中。

答案 1 :(得分:1)

如果Reference<T>的变量类型为T,则T不能包含Reference<T>类型的变量。您的替代方案是重写Reference<T>,或重写Bunny以使用指向Reference<T>的指针:

template<class> class Reference;

class Bunny
{
    ...
private:
    Reference<Bunny>* parent;
}

答案 2 :(得分:0)

这不仅仅是抽象问题,抽象成为解决问题的方法吗?我考虑创建一个接口IBunny,然后在任何实现Reference<IBunny>的定义中使用IBunny

这是发明接口的用例之一(在典型的GoF创建模式中派上用场)。