内联文件之间的循环依赖性

时间:2016-01-30 00:58:18

标签: c++ templates inline circular-dependency

在我的数学库中我用C ++创建,我有一个Quaternion类和一个Vector3类。它们的布局如下:

Vector3.hpp:

#pragma once

template<typename T>
struct Vector3
{
   //...
};

template<typename T>
Vector3<T> operator+(Vector3<T> lhs, Vector3<T> rhs);

#include "Vector3.inl"

Vector3.inl

template<typename T>
Vector3<T> operator+(Vector3<T> lhs, Vector3<T> rhs)
{
    return Vector3<T>(lhs.x+rhs.x, lhs.y+rhs.y, lhs.z+rhs.z);
}

//...

Quaternion类的布局相同。

目前我使用Quaternion类的Vector3类用于函数参数,因此它#includeVector3.hpp标题。但现在我需要使用Quaternion类中的Vector3类来实现某些功能。

由于这仅在函数的实现中需要,我通常只将#include放在源文件中,但由于我使用内联文件,并且它们包含在头文件中,这样做只会导致一堆编译器错误,因为它们相互依赖。

当我只能使用标题/内联文件时,如何解决这种循环依赖?

1 个答案:

答案 0 :(得分:0)

处理循环依赖的最佳方法是首先避免它!花一些时间重新考虑设计,改变功能,拆分类等是明智的。

让我们假设没有循环依赖的情况如下:

template <typename T>
struct Vector{
 ...
};

template<typename T>
struct VectorUser{
   Vector<T> v;
   ...
};

如果可以通过前向声明解决循环依赖问题,例如:

template <typename T>
struct Vector{
  void printout(const VectorUser<T> &user);
  ...
};

VectorUser的前向声明与Vector<T>::printout()声明后VectorUser的声明,即 VectorUser.inl (毕竟,没有人可以使用Vector)无论如何不包括 VectorUser.h )会产生所需的结果:

//Vector.h:
template <typename T>
struct VectorUser;


template <typename T>
struct Vector{
  void printout(VectorUser<T> &user);
  ...
};

//VectorUser.h:
template<typename T>
struct VectorUser{...} 
};

template<typename T>
void Vector<T>::printout(VectorUser<T> &user){
   user.printout();
}

但如果前瞻声明还不够呢?例如:

template <typename T>
struct Vector{
  VectorUser<T> user;
  ...
};

好吧,即使没有模板也不会让它编译。我在代码中经常看到至少两个选项:

  1. 使Vector<T>::user成为指针/引用,因此前向声明就足够了。

  2. Vector<T>拆分为两个类:VectorUser中使用的一个基类和另一个基类,所有功能都取决于VectorUser

  3. 我会提倡第二种解决方案,但它可能并不总是可行的。