简体   繁体   English

具有继承的模板类的循环依赖

[英]Circular Dependency with Inherited Template Class

I'm having a circular dependency problem. 我有一个循环依赖问题。 Basically I have two classes, the first is a template class which uses some functionality from my second class. 基本上我有两个类,第一个是模板类,它使用第二个类的某些功能。 The second class inherits from my template class. 第二个类继承自我的模板类。

Below is a simplified structure: 下面是一个简化的结构:

// 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
}

Now the problem is when I complile the code I am getting the following errors in bar.h 现在的问题是当我编译代码时,我在bar.h中遇到以下错误

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

From what I can tell this a definitely a dependency problem. 据我所知,这绝对是一个依赖问题。 If I remove the call to 'LogEvent' from within 'DoSomething', and remove reference "Bar.h" from Foo.h the issue goes away. 如果我从“ DoSomething”中删除对“ LogEvent”的调用,并从Foo.h中删除引用“ Bar.h”,则问题将消失。

However it's not really a solution because Foo needs functionality contained with Bar, conversely bar inherits from Foo and needs to include a reference to Foo.h. 但是,这并不是真正的解决方案,因为Foo需要Bar包含的功能,相反,bar继承自Foo,并且需要包含对Foo.h的引用。

So - how can I resolve this problem? 所以-我该如何解决这个问题? I have looked through the other posts regarding circular references but I haven't been able to solve the problem. 我浏览了其他有关循环引用的文章,但无法解决问题。

Thanks 谢谢

Based on the code you've posted, foo.h does not need to include bar.h, and the problem will go away if it doesn't. 根据您发布的代码,foo.h不需要包含bar.h,如果没有,问题将消失。

The important thing is that the compiler see Foo before it sees Bar, and this may not happen if #include "bar.h" is at the top of foo.h (depending on what order foo.h and bar.h are #include ed in the consuming modules). 重要的是编译器在看到Bar之前先看到Foo,并且如果#include "bar.h"在foo.h的顶部(取决于foo.h和bar.h的顺序是#include则可能不会发生使用者模块中的版本)。

That said, if a base class needs to assume a specific derived class and call into it by name, it seems like there is probably a design issue (would a virtual function in the base work?). 就是说,如果基类需要假设一个特定的派生类并按名称进行调用,则似乎可能存在设计问题(基工作中是否需要虚函数?)。 But I can't make that judgment without seeing whole picture. 但是我不能不看全盘就做出这样的判断。

Based on the comments below, I think you can solve the immediate problem by adding a third file: 根据以下评论,我认为您可以通过添加第三个文件来解决当前的问题:

// LogEvent.h

void LogEvent(...);

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

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

Then modify foo.h as follows: 然后按如下所示修改foo.h:

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

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

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

Unless there are other issues too, that should at least get you compiling. 除非也有其他问题,否则至少应该使您编译。

Your problem is the definition of the function: 您的问题是函数的定义:

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

You don't need write Bar class name here. 您无需在此处写Bar类名称。

use: 采用:

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

That way, when you write Foo<Bar> Bar will replace T . 这样,当您编写Foo<Bar> Bar将替换T

I tested the change with the code you posted and it worked. 我用您发布的代码测试了更改,并且该更改有效。

EDIT: 编辑:

Well I found a solution using Template Specialization . 好吧,我找到了使用模板专业化的解决方案。

Add this to your Foo.h : 将此添加到您的Foo.h

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

This solve all your problems. 这样可以解决您所有的问题。 Using template specialization, if the template Foo is instantiated with the Bar type as argument, you will be instantiating the class defined above instead the original Foo . 使用模板专用化,如果模板FooBar类型作为参数实例化,则您将实例化上面定义的类而不是原始Foo

So, you don't have to worry any more about others classes don't have the method GetInstance . 因此,您不必担心其他类没有GetInstance方法。 And you can use this approach to expand your code and use as many specializations of Foo as you want. 而且,您可以使用这种方法来扩展代码,并根据需要使用Foo许多专业化功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM