C++ 中两个类的互相引用导致 unresolved external symbol 的问题

guy_1 发布于 2016/06/16 09:25
阅读 406
收藏 0
c++

编译环境:Visual Studio 2015 Community Edition

定义了两个类,Matrix4x4,表示一个 4x4 的矩阵,Vector4 表示一个四维向量。在 Matrix4x4 中重载 [] 返回它的一个行向量,重载 () 返回它的某一个元素;在 Vector4 中重载 * 来处理行向量右乘一个矩阵,这两个类需要互相引用,我做了下面的处理:

// Matrix4x4.h
#pragma once

namespace MiniMathLib
{
    class Vector4;

    class Matrix4x4
    {
    public:
        Matrix4x4();
        Matrix4x4(const Vector4 &r0, const Vector4 &r1, const Vector4      &r2, const Vector4 &r3);
        Matrix4x4(const Matrix4x4 &m);
        
        // 返回位于矩阵 r 行,c 列的元素
        inline float operator()(int r, int c) const;
        // 返回矩阵的第 r 行
        inline Vector4 operator[](int r) const;
 
    private:
        float m[4][4];
    };
}

// Vector4.h
#pragma once

namespace MiniMathLib
{
    class Matrix4x4;

    class Vector4
    {
    public:
        float x, y, z, w;

        Vector4();
        Vector4(float x, float y, float z, float w); 
        Vector4(const Vector4 &v);
        
        Vector4 operator+(const Vector4 &v) const;
        Vector4 operator-(const Vector4 &v) const;
        Vector4 operator*(float f) const;
        Vector4 operator*(const Vector4 &v) const;
        friend Vector4 operator*(float f, const Vector4 &v);
        // 行向量与 4x4 矩阵的相乘
        Vector4 operator*(const Matrix4x4 &m) const;
    };
}

// Matrix4x4.cpp
#include "Matrix4x4.h"
#include "Vector4.h"

namespace MiniMathLib
{
    // 省略一些函数定义
    
    float Matrix4x4::operator()(int r, int c) const
    {
        return m[r][c];
    }

    float Matrix4x4::operator[](int r) const
    {
        return Vector4(m[r][0], m[r][1], m[r][2], m[r][3]);
    }
}

// Vector4.cpp
#include "Vector4.h"
#include "Matrix4x4.h"

namespace MiniMathLib
{
    // 省略一些函数定义

    Vector4 Vector4::operator*(const Matrix4x4 &m) const
    {
        return x * m[0] + y * m[1] + z * m[2] + w * m[3];
    }
}



现在的问题是,在编译这段代码时,在 Vector4.obj 中找不到 Matrix4x4::operator[] 的符号(unresolved external symbol),最初以为是在 Matrix4x4::operator[] 中我引用了 Vector4,又是互相引用的问题。尝试将 

Vector4 operator*(const Matrix4x4 &m) const;



胡乱改写为

Vector4 Vector4::operator*(const Matrix4x4 &m) const
{
    m(0, 0);
    return Vector4();
}



但仍然是找不到 Matrix4x4::operator() 这个符号,现在我一时无法看清楚问题的原因,希望能得到一些指点。先谢谢了。

加载中
0
石头左边
石头左边
去掉inline试试
guy_1
guy_1
回复 @石头左边 : 嗯,现在心里平静了 :-)
石头左边
石头左边
回复 @guy_1 : 补充一句:不要为函数不能是inline而遗憾。 :)
石头左边
石头左边
回复 @guy_1 : 解决就好!
guy_1
guy_1
对的!我后来就是意识到是 inline 的问题!现在我将 inline 的定义放到了头文件中,而不是 cpp 文件中。但由于1. 类之间的互相引用 2. inline 函数定义在头文件中。这样一来,原则应该设计为 inline 的函数就不得不设计为非 inline 函数了.
0
zhujianbest
zhujianbest

inline Vector4 operator[](int r)const; 

需要包含Vector4的头文件,如果是引用和指针就不需要,class声明就行了

guy_1
guy_1
现在我在 Matrix4x4.h 中添加了 #include "Vector4.h" 仍然还是报找不到符号的错误。
0
乌合之众
乌合之众

因为

class Vector4;  // 前置声明
 
// 返回矩阵的第 r 行
inline Vector4 operator[](int r) const;
// 上面返回的是一个Vector4对象,所以需要知道这个对象的内存布局,而前置声明不能做到。



你应该需要将  class Vector4; 删掉,然后 在 Matrix4x4.h 中添加 #include "Vector4.h" 

你的代码还有别的错误,你仔细看一下。

0
guy_1
guy_1

引用来自“乌合之众”的评论

因为

class Vector4;  // 前置声明
 
// 返回矩阵的第 r 行
inline Vector4 operator[](int r) const;
// 上面返回的是一个Vector4对象,所以需要知道这个对象的内存布局,而前置声明不能做到。



你应该需要将  class Vector4; 删掉,然后 在 Matrix4x4.h 中添加 #include "Vector4.h" 

你的代码还有别的错误,你仔细看一下。

谢谢,不过这样也是不可以的。现在大致的原因,我将一些函数声明为了 inline,但对它们的定义却放在了相应的 cpp 文件中,这样在链接时找不到相应的符号,应该是不能将 inline 定义在 cpp 文件中的。忽然想起来《C++ Primer》里提到的一个原则,将 inline 定义到类的声明所在的头文件中,因为 inline 函数是文件作用域的,因此即使多个 cpp 文件都包含了这个头文件也不会违背 one definition 的原则。这样就编译通过了。

由于互相引用的存在,原则上应该 inline 的函数总是存在不能设计为 inline 的限制,就因为 inline 定义在了头文件里。

返回顶部
顶部