c++ - 使用模板时避免循环依赖问题

标签 c++ templates circular-dependency

我遇到了一个问题,这很可能是循环依赖类的前向声明错误引起的。但是前向声明模板类(类似于here)似乎还是不行。

使用 visual studio express edition 2013 我收到 LNK 4221 警告(未定义新符号)导致 LNK 2019(未解析的外部符号)。

以下是导致问题的 header :

3d vector

#ifndef VEC3_H
#define VEC3_H

// Standard library
#include <iostream>
#include <sstream>

// Internal
#include "SMath.h"
#include "Quaternion.h"

namespace Sapling {
    template <typename T>
    class Quaternion; ///< Forward

    template <typename T> class Vec3 {
    public:
        // ...
        void rotate(Vec3<T> axis, T radAngle) {
        T sinHalfAngle = Math::sin(radAngle / 2);
        T cosHalfAngle = Math::cos(radAngle / 2);

        // Make a new quaternion [cos(w)|sin(w) vec]
        Quaternion<T> rotation(axis.x * sinHalfAngle,
                               axis.y * sinHalfAngle,
                               axis.z * sinHalfAngle,
                               cosHalfAngle);
        // Conjugate the rotation to eliminate the imaginary part
        Quaternion<T> conjugate = rotation.getConjugate();

        Quaternion<T> result = conjugate * (*this) * rotation; ///< frtl

        x = result.x;
        y = result.y;
        z = result.z;
        }
        // ...

        T x;
        T y;
        T z;
    };
}
#endif

四元数

#ifndef QUATERNION_H
#define QUATERNION_H

// Standard library
#include <iostream>
#include <sstream>

// Internal
#include "Vec3.h"

namespace Sapling {
    template <typename T>
    class Vec3; ///< Forward
    template <typename T> class Quaternion {
    public:
        // ...
        Quaternion(Vec3<T> vec, T W) : x(vec.x), y(vec.y), z(vec.z), w(W) { }
        // ...
        // Relational vector operators
        void operator*= (const Vec3<T>& v) {
            x = -(x * v.x) - (y * v.y) - (z * v.z);
            y = (w * v.x) + (y * v.z) - (z * v.y);
            z = (w * v.y) + (z * v.x) - (x * v.z);
            w = (w * v.z) + (x * v.y) - (y * v.x);
        }
        // ...

        T x;
        T y;
        T z;
        T w;
    };
}
#endif ///< Include guard

我知道这两个类的数据应该是私有(private)的,但到目前为止我无法解决它......

那么你能解释一下为什么这仍然会导致循环依赖吗?
谢谢,祝你有美好的一天:)

最佳答案

作为一个简单的解决方案,我建议将Quaternion 分成两个类,QuaternionBase 不需要Vec3,和Quaternion 本身是 QuaternionBase 的子类,并从 Vec3 引入构造函数:

// Vec3.h
...
#include <QuaternionBase.h>
...
template <typename T> class Vec3 {
public:
    // ...
    void rotate(Vec3<T> axis, T radAngle) {
        ...
        QuaternionBase<T> rotation(axis.x * sinHalfAngle,

// QuaternionBase.h
template <typename T> class QuaternionBase {
public:
    // all operations expect the constructor accepting Vec3

// Quaternion.h
#include <QuaternionBase.h>
#include <Vec3d.h>
template <typename T> class Quaternion : public QuaternionBase {
public:
    // ...
    Quaternion(Vec3<T> vec, T W) : QuaternionBase(vec.x, vec.y, vec.z, W) { }

另一种解决方案是为 Vec3d 创建一个基类,并将访问操作(.x 等)移到那里。

第三种解决方案是使 Quaternion(Vec3, T) 构造函数模板化如下

template<typename Vec>
Quaternion(Vec vec, T W) : x(vec.x), y(vec.y), z(vec.z), w(W) { }

希望这不会在代码的其他部分引入额外的歧义。

关于c++ - 使用模板时避免循环依赖问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30437987/

相关文章:

gradle - 升级到 Gradle 5 时的循环依赖

javascript - Angular : circular dependency of specific case

c++ - 用于快速查找 2 个键的最快数据结构或算法

c++ - 从字符串转换为 LPCTSTR 时遇到问题

javascript - 避免 Node require() 的循环依赖?

c++ - 重载运算符 '==' 时出现问题。需要能够使用模板处理字符串、 double 和日期

c++ - 简单的C++模板定义问题

c++ - Visual Studio 项目文件

c++ - 没有匹配函数调用 sscanf

c++ - 如何解包类型定义的类型?