循环模板类的循环依赖

时间:2014-04-28 15:06:04

标签: c++ templates inheritance circular-dependency circular-reference

我遇到循环依赖问题。基本上我有两个类,第一个是模板类,它使用我的第二个类的一些功能。第二个类继承自我的模板类。

以下是一个简化的结构:

// Foo.h
#pragma once
#include "Bar.h"

template <class T> class Foo
{
     public:
        void DoSomething();
};

template <class T> void Foo<T>::DoSomething()
{
     Bar::GetInstance()->LogEvent();
}


//Bar.h
#pragma once
#include "Foo.h"

class Bar : public Foo<Bar>
{
    public:
        static Bar* GetInstance();
        void LogEvent();
};


//Bar.cpp
#include "Bar.h"

Bar* Bar::GetInstance()
{
     // return instance of Bar singleton class
}

void Bar::LogEvent()
{
     // log some event in a file
}

现在的问题是,当我编译代码时,我在bar.h中遇到以下错误

Bar.h() : error C2504: 'Foo' : base class undefined
Bar.h() : error C2143: syntax error : missing ',' before '<'

从我所知道的这绝对是一个依赖性问题。如果我从'DoSomething'中删除对'LogEvent'的调用,并从Foo.h中删除引用“Bar.h”,则问题就会消失。

然而,它并不是一个真正的解决方案,因为Foo需要Bar中包含的功能,反过来禁止从Foo继承,并且需要包含对Foo.h的引用。

那么 - 我该如何解决这个问题呢?我查看了有关循环引用的其他帖子,但我无法解决问题。

由于

2 个答案:

答案 0 :(得分:0)

根据您发布的代码,foo.h不需要包含bar.h,如果没有,问题就会消失。

重要的是编译器在看到Bar之前会看到Foo,如果#include "bar.h"位于foo.h的顶部,这可能不会发生(取决于foo.h和bar.h的顺序是什么{ {1}}在消费模块中编辑。)

也就是说,如果一个基类需要假定一个特定的派生类并按名称调用它,似乎可能存在设计问题(基础中的虚函数会起作用吗?)。但是,如果不能全面了解,我无法做出判断。

根据以下评论,我认为您可以通过添加第三个文件解决当前问题:

#include

然后按如下方式修改foo.h:

// LogEvent.h

void LogEvent(...);

// LogEvent.cpp
#include "bar.h"

void LogEvent(...)
{
   Bar::GetInstance()->LogEvent(...);
}

除非还有其他问题,否则至少应该让你编译。

答案 1 :(得分:0)

你的问题是函数的定义:

template <class T> void Foo<T>::DoSomething()
{
     Bar::GetInstance()->LogEvent();
}

此处不需要编写Bar班级名称。

使用:

template <class T> void Foo<T>::DoSomething()
{
     T::GetInstance()->LogEvent();
}

这样,当你写Foo<Bar> Bar时会替换T

我使用您发布的代码测试了更改,但是它有效。

修改

我找到了使用模板专业化的解决方案。

将此添加到您的Foo.h

template <>
class Foo<Bar>
{
     public:
        void DoSomething()
        {
             Bar::GetInstance()->LogEvent();
        }
};

这解决了所有问题。使用模板特化,如果模板FooBar类型为参数进行实例化,您将实例化上面定义的类而不是原始Foo

因此,您不必再担心其他类没有方法GetInstance。您可以使用此方法扩展代码,并根据需要使用Foo的任意数量的专业化。