具有模板函数的循环依赖关系
Circular dependency with template function
我有一个具有以下声明的类a(a.h文件):
#ifndef __A_DEFINED__
#define __A_DEFINED__
class A
{
public:
template<typename T> inline void doThat() const;
};
#endif
以及从该类派生的类B(B.h文件):
#ifndef __B_DEFINED__
#define __B_DEFINED__
#include <iostream>
#include "A.h"
class B : public A
{
public:
void doThis() const { std::cout << "do this!" << std::endl; }
};
#endif
到目前为止,一切都很好。我的问题是函数A::doThat()使用B::doThis():
template<typename T> inline void A::doThat() const { B b; b.doThis(); }
通常,循环依赖关系不会成为问题,因为我只会在.cpp文件中定义A::doThat()。然而,在我的例子中,doThat是一个模板函数,所以我不能这么做。
以下是我迄今为止设想的解决方案:
在.cpp文件中定义模板函数
A::doThat()
。问题是,我需要用各种模板参数显式实例化所有调用(在实际情况下可能有很多)。在A.h中声明A类之后,添加
#include "B.h"
,然后定义A::doThat()
函数。这在visual studio中运行良好,但g++不喜欢它。
有没有一种巧妙的方法来解决这个问题?
EDIT:在实际情况中,不仅有一个子类B,还有多个子类(B、C、D等)。函数A::doThat()依赖于所有子类。函数B::doThis()也是模板化的。
B
类的默认模板参数可以工作:
#include <iostream>
// include A.h
class B;
class A
{
public:
template<typename T, typename U = B> inline void doThat() const
{
U b; b.doThis();
}
};
// include B.h
class B : public A
{
public:
void doThis() const { std::cout << "do this!" << std::endl; }
};
// main
int main()
{
A a;
a.doThat<int>();
}
通常,允许父函数调用子函数的最佳方法是在父函数中将该函数声明为纯虚拟函数,并在子函数中重写它。
#include <iostream>
class A
{
public:
virtual ~A() = default;
template<typename T> inline void doThat() const
{
// do some other stuff
doThis();
}
virtual void doThis() const = 0; // pure virtual function
};
class B: public A
{
public:
void doThis() const override
{
std::cout << "do this!" << std::endl;
}
};
int main()
{
B b;
A* ap = &b;
ap->doThat<int>();
}
以下内容适用于g++
:
文件A.h
:
#ifndef __A_DEFINED__
#define __A_DEFINED__
class A
{
public:
template<typename T> inline void doThat() const;
};
#include "B.h"
template<typename T> inline void A::doThat() const { B b; b.doThis(); }
#endif
文件B.h
:
#include <iostream>
#include "A.h"
// We check for the include guard and set it AFTER the inclusion of A.h
// to make sure that B.h is completely included from A.h again.
// Otherwise the definition of A::doThat() would cause a compiler error
// when a program includes B.h without having included A.h before.
#ifndef __B_DEFINED__
#define __B_DEFINED__
class B : public A
{
public:
void doThis() const { std::cout << "do this!" << std::endl; }
};
#endif
文件test_A.cpp
:
// In this test case we directly include and use only A.
#include "A.h"
#include "A.h" // We test whether multiple inclusion causes trouble.
int main() {
A a;
a.doThat<int>();
}
文件test_B.cpp
:
// In this test case we directly include and use only B.
#include "B.h"
#include "B.h" // We test whether multiple inclusion causes trouble.
int main() {
B b;
b.doThat<int>();
b.doThis();
}
替代方案:
我不知道你(或一些编码约定)是否坚持为每个类单独的头文件,但如果不是,以下应该有效:
您可以将class A
和class B
以及成员函数模板A::doThat<typename>()
的定义(按此顺序)放在一个头文件AandB.h
(或您喜欢的任何名称)中。
这需要多态性。使用多态性有两种选择:
-
动态多态性,即使
A
成为抽象基类,并虚拟调用doThis()
:struct A { virtual void do_this() const = 0; template<typename T> void doThat() const { doThis(); } }; struct B : A { void doThis() const override { /* ... */ } };
当然,只有在
doThis()
没有模板化的情况下,这才有效。如果你需要,你可以使用 -
静态多态性,即CRTP,当
template<typename Derived> struct A { template<typename T> void doThat() const { static_cast<const Derived*>(this)->template doThis<T>(); } }; struct B : A<B> { template<typename T> void doThis() const { /* ... */ } };
如果(在您的示例代码中)B::doThis()
不是为同一个对象调用的,而是为某个临时对象调用,则可以
template<typename typeB>
struct A
{
template<typename T>
void doThat() const { typeB b; b.template doThis<T>(); }
};
- C++GTKMM gui循环依赖关系
- 如何在头文件中声明类模板(由于循环依赖关系)
- 如何在具有循环依赖的类中dynamic_cast?
- C++模板方法中的循环依赖关系
- 修复循环依赖项 c++17 标头
- 涉及全局对象的循环依赖C++
- 循环依赖,在继承类的情况下使用覆盖方法
- Wt::D bo 中的循环依赖关系
- 在包含窗口标头时难以解决循环依赖关系问题
- 解决循环依赖关系 c++ 的想法
- C++循环依赖关系,未声明的标识符
- C++ 中的循环依赖关系问题
- 错误 C2512 视觉C++(并且不是循环依赖项)
- CMake 外部和内部静态库的循环依赖关系
- 正在从继承中解析循环依赖项
- "std::shared_ptr"循环依赖关系是如何导致问题的
- 纯引用而不是weak_ptr来打破循环依赖关系
- "invalid use of incomplete type" .解决循环依赖关系
- 如何避免模板方法的循环依赖
- 循环依赖结构,使用前向声明时结构的错误重定义