多翻译单元中的内联函数 让我们从下面的C++文件集开始: // my_class.h struct MyClass { void my_func(); }; void MyClass::my_func() {} // f.h void f1(); void f2(); // f1.cpp #include "my_class.h" void f1() { MyClass a; a.my_func(); } // f2.cpp #include "my_class.h" void f2() { MyClass a; a.my_func(); } // main.cpp #include "f.h" int main() { f1(); f2(); return 0; }

多翻译单元中的内联函数 让我们从下面的C++文件集开始: // my_class.h struct MyClass { void my_func(); }; void MyClass::my_func() {} // f.h void f1(); void f2(); // f1.cpp #include "my_class.h" void f1() { MyClass a; a.my_func(); } // f2.cpp #include "my_class.h" void f2() { MyClass a; a.my_func(); } // main.cpp #include "f.h" int main() { f1(); f2(); return 0; },c++,C++,我试着用 $ g++ f1.cpp f2.cpp main.cpp 显然,链接器抱怨重复符号my_func: duplicate symbol __ZN7MyClass7my_funcEv in: /var/folders/yj/zz96q16j6vd1dq1_r3mz8hzh0000gn/T/f1-962ae7.o /var/folders/yj/zz96q16j6vd1dq1_r3mz8hzh0000gn/T/f2-aef78c.o ld: 1 duplicate symb

我试着用

$ g++ f1.cpp f2.cpp main.cpp
显然,链接器抱怨重复符号
my_func

duplicate symbol __ZN7MyClass7my_funcEv in:
    /var/folders/yj/zz96q16j6vd1dq1_r3mz8hzh0000gn/T/f1-962ae7.o
    /var/folders/yj/zz96q16j6vd1dq1_r3mz8hzh0000gn/T/f2-aef78c.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
我的下一次尝试是在类定义中移动函数定义,因此我们得到:

struct MyClass
{
  void my_func()
  {}
};
运行相同的
g++
命令,程序编译成功。这是因为类定义中定义的函数被隐式标记为
inline
(§10.1.6*3)

该标准规定:

带有内联说明符的函数声明(11.3.5、12.2.1、14.3)声明内联函数。内联说明符向实现表明,在调用点对函数体进行内联替换要优于通常的函数调用机制。在调用点执行此内联替换不需要实现;但是,即使省略了此内联替换,也应遵守本节中规定的内联函数的其他规则

这似乎与上面写的有些矛盾:

因为函数的关键字inline的意思是“允许多个定义”,而不是“首选内联”[…]

据我所知,在类定义中定义一个函数会使它隐式地
内联
,这并不一定意味着编译器会选择内联它的主体,而是会在每个翻译单元中定义它。这是正确的吗

第二个问题是关于模板类。分离模板类的声明/定义是一个问题,如上所述,因此我们只能在类定义中使用函数定义,这使得它隐式地
内联
,对吗?这有什么影响


由于当类是模板时,我们只能选择在类定义中定义函数,那么对于非模板的类该怎么办?我们是否应该在源文件中定义函数,并且尽可能只在头文件中保留声明

据我所知,在类定义中定义一个函数会使它隐式地
内联
,这并不一定意味着编译器会选择内联它的主体,而是会在每个翻译单元中定义它。这是正确的吗

对。当在类中定义时,它被标记为内联,并且可以将该防御引入多个翻译单元。编译器将为您处理该问题

第二个问题是关于模板类。分离模板类的声明/定义是一个问题,如上所述,因此我们只能在类定义中使用函数定义,这使得它隐式地
内联
,对吗?这有什么影响

这是不对的。模板是特殊的。一旦代码被编译,它们实际上并不存在。模板是什么,是一个冲压出类或函数的方法。因此,允许模板包含在使用它的每个翻译单元中,这样编译器就可以根据需要从中删除一个具体的类/函数。这意味着您可以在类之外定义类成员函数


由于当类是模板时,我们只能选择在类定义中定义函数,那么对于非模板的类该怎么办?我们是否应该在源文件中定义函数,并且尽可能只在头文件中保留声明


通常,您希望将定义放入cpp文件中。这样做的好处是,如果更改函数的实现,只需重新编译一个cpp文件。如果它们在头文件中,则需要重新编译包含该头文件的每个cpp文件,这会导致生成时间更长。

问题是,在您的情况下,
my_func
未在类定义中定义。它只在那里声明。@NO_NAME第二个例子正好说明了这一点:在类定义中包含函数定义“因为当类是模板时,我们只能选择在类定义中定义函数”这不是真的,所以问题的其余部分没有用“第二个问题来了”每个问题一个问题please@Victor是的,不要想太多,包括警卫。它们是有用的,但在这个问题的上下文中毫无意义。
模板需要包含在使用它的每个翻译单元中
-词汇选择不当。只需包含模板的声明。您可以将定义放在一个翻译单元中,并显式实例化它。@NO\u NAME我正在更新措辞。更好?