我在文件Dimension.h中定义了一个类Dimension
(就像我的所有类一样):
class Dimension
{
public:
constexpr Dimension() noexcept;
constexpr Dimension(int w, int h) noexcept;
int width;
int height;
};
我认为我可以像在所有课程中一样,将定义放在一个单独的Dimension.cpp中:
#include "Dimension.h"
constexpr Dimension::Dimension() noexcept : width(0), height(0) {}
constexpr Dimension::Dimension(int w, int h) noexcept : width(w), height(h) {}
但是当我尝试使用该类时,编译器会告诉我:
警告:内联函数“constexpr Dimension::Dimension()
”已使用但未定义
和链接时:
对“pong::graphics::Dimension::Dimension()
”
(与其他构造函数相同)
如果我在标题中定义类,那么:
class Dimension
{
public:
constexpr Dimension() noexcept : width(0), height(0) {}
constexpr Dimension(int w, int h) noexcept : width(w), height(h) {}
int width;
int height;
};
并省略.cpp文件,一切正常。
我正在使用GCC 4.9.2。为什么单独的定义不起作用?
答案 0 :(得分:41)
如果标头内未定义constexpr
函数,编译器在编译所有其他源文件时无法看到constexpr
函数的定义。
显然,如果它看不到函数的定义,它就无法在编译时执行计算它们所需的步骤。因此,必须在使用它们的任何地方定义所有constexpr
函数。
谢谢@IgorTandetnik:
[dcl.constexpr]§7.1.5/ 2
constexpr
函数和constexpr
构造函数是隐式内联的。
[basic.def.odr]§3.2/ 4
内联函数应在每个使用它的翻译单元中定义。
答案 1 :(得分:8)
您所要求的内容可以完成,但有一个显着的限制: constexpr 功能只能从定义它的翻译单元(即源文件)内部调用。这不适用于您给出的示例,因为构造函数应该是类的一部分。公共界面。然而,它在其他情况下非常有用,例如将私有方法定义为 constexpr ,然后在需要在编译时知道的表达式中使用它们的返回值,例如:模板实例化,切换语句标签等