我正在阅读pbrt,它已经定义了一个类型:
template <int nSpectrumSamples>
class CoefficientSpectrum;
class RGBSpectrum : public CoefficientSpectrum<3> {
using CoefficientSpectrum<3>::c;
typedef RGBSpectrum Spectrum;
// typedef SampledSpectrum Spectrum;
作者说:
“我们还没有编写系统,以便可以在运行时解决使用哪个Spectrum实现的选择;要切换到不同的表示形式,必须重新编译整个系统。这种设计的一个优势是许多各种Spectrum方法可以实现为编译器可以内联的短函数,而不必留为必须通过相对较慢的虚拟方法调用机制调用的独立函数。性能上的实质性改善。”
1。为什么模板可以内联功能,但常规方式不能内联?
2。为什么通常的方法必须使用虚拟方法?
链接到整个头文件: https://github.com/mmp/pbrt-v3/blob/master/src/core/spectrum.h
答案 0 :(得分:7)
要内联函数调用,编译器必须知道1.调用了哪个函数,以及2.该函数的确切代码。 virtual
函数的整个目的是推迟对调用哪个函数的运行时间的选择,因此编译器只能使用需要非常特殊的环境 1 。
模板和虚函数(即多态)都是编码抽象的工具。使用CoefficientSpectrum
的代码并不真正在乎频谱的实现细节,只有您可以例如将其与RGB进行转换-这就是为什么它使用抽象(以避免为每种光谱重复代码)的原因。正如您引用的注释中所解释的那样,在这里使用多态性进行抽象意味着编译器很难优化代码,因为它从根本上推迟了对运行时的选择(有时是有用的,但在这里并非绝对必要)。通过要求在编译时选择实现方式,编译器可以轻松地优化(即内联)代码。
1 例如,某些编译器能够优化std::function
抽象,该抽象通常使用多态来进行类型擦除。当然,这只有在所有必要的信息都可用的情况下才能起作用。