0

我有一个包含矩阵管理逻辑的类。同时我有一套方法专门用于处理一些重要的时间花费矩阵操作操作(如 LU 分解等)。

该类使用该文件中定义的函数。该文件需要有权访问该类的元素。我需要让那些专门的方法成为上述课程的朋友。这导致我在每个其他标题中包含一个标题。

我的问题

我之前描述的情况在这里编码如下。第一个代码是指mat.hpp.

#ifndef MAT_HPP
#define MAT_HPP
#include "operations.hpp"
namespace nsA {
template <typename T>
// Templated class because matrices can be real or complex
class mat {
   // Members...
   friend template <typename U> 
   void exec_lu(const mat<U>& in, const mat<U>& out);
   // Members...
} /* class end */
}
#endif
#endif

第二个文件是operations.hpp

#ifndef OPERATIONS_HPP
#define OPERATIONS_HPP
#include "mat.hpp"
namespace nsA {
namespace nsB {
template <typename T>
void exec_lu(const mat<T>& in, const mat<T>& out);
}
}
#endif

问题是编译器开始抱怨。

笔记

请考虑一下,如果我在其中评论了朋友声明mat.hpp但留下了包含,编译器会告诉我在“operations.hpp”mat中没有定义类型!

如果还注释包含mat.hpp并保持朋友声明也注释,编译器就可以了!

如何解决这个问题?

谢谢

4

2 回答 2

2

你可以通过添加几个前向声明来做到这一点......但是你甚至可以用更多的代码做得更好:

template <typename T> class mat;
template <typename T> void exec_lu( const mat<T>&, const mat<T>& );
template <typename T>
class mat {
   friend void exec_lu<T>( const mat<T>&, const mat<T>& );
};
template <typename T>
void exec_lu( const mat<T>& a, const mat<T>& b ) { ... }

这种方法和你的方法之间的主要区别(除了修复语法限制)是,在这种方法中,单个实例化exec_lu被授予访问权限mat<T>,特别是需要访问它的实例化。在您的代码中(修复后),所有专业化exec_lu都可以访问任何专业化mat(即exec_lu<int>可以访问mat<int>私有成员,但也mat<double>...),您可能不希望这样。

有关声明模板朋友的不同选项的详细说明,请阅读相关问题的答案。

于 2012-06-29T03:30:07.187 回答
1

要使其正常工作,您需要转发声明该类。它看起来像这样:

文件 mat.hpp:

#ifndef MAT_HPP
#define MAT_HPP
namespace nsA {
template <typename T>
class mat;
namespace nsB {
  template <typename T> 
  void exec_lu(const mat<T>& in, const mat<T>& out);
}
template <typename T>
class mat {
   friend void exec_lu(const mat<T>& in, const mat<T>& out);
};
}
#endif

和文件操作.hpp:

#ifndef OPERATIONS_HPP
#define OPERATIONS_HPP
#include "mat.hpp"
namespace nsA { namespace nsB {
template <typename T>
void exec_lu(const mat<T>& in, const mat<T>& out);
}}
#endif

你最初的宣言比我的更能传递友谊。我的只为与类的类型名匹配的函数授予友谊。

于 2012-06-29T03:25:16.563 回答