没有内联函数的没有.cpp文件的c ++类?

时间:2014-03-19 09:59:19

标签: c++ templates c++11 linker

我已经问了一个类似的问题,但这个问题有点不同

我不想为每个简单的c ++类编写.cpp文件。

当我在单个.hpp文件中编写类定义和声明时,链接器会抱怨成员函数的多个定义,这些函数没有在类的主体内部实现或者使用内联键盘定义。

例如,这将起作用,但成员函数将变为内联:

// log.hpp file
#pragma once
#include<iostream>

class log {
  private:
    static int m_cnt = 0;
  public:
    void log();
};

inline void log::log() {
    std::cout << ++m_cnt << std::endl;
}

所以我使用模板来摆脱链接器投诉,并希望成员函数不会内联(是吗?):

// log.hpp file
#pragma once
#include<iostream>

template<typename T>
class log_t {
  private:
    static int m_cnt = 0;
  public:
    void log();
};

template<typename T>
void log_t<T>::log() {
    std::cout << ++m_cnt << std::endl;
}

// some random type (int)
typedef log_t<int> log;

然后我可以简单地在多个.cpp文件中使用日志类而不会有链接器投诉。

即使我使用此方法,成员函数也会成为内联函数吗?

2 个答案:

答案 0 :(得分:5)

通常,在头文件中使用每个实现都是一个不好的想法,因为它可能导致较大项目的编译时间非常长。使用模板来避免这种情况也不是一个好主意,因为它不会改变这一事实。

inline只是对编译器的一个提示;它可能会忽略它并内联您的模板代码。简而言之:你的问题的答案无关紧要。标准/最佳方法是使用.cpp文件进行实现,即使您想避免它。

答案 1 :(得分:5)

虽然将所有内容放在一个.h文件中通常是不好的做法,但有些情况下这样做会更方便。特别是在定义小类时,以及在原型设计阶段,代码可以快速改变很多。

我真的不建议使用模板来解决链接问题,因为它会减慢编译速度并导致混淆:它就像创建一个函数,当你除了那个参数总是具有相同的值。无论如何,键入inlinetemplate<typename T>;)

更短

因此,您必须在类体中定义方法,或者如果在体外定义,则使用inline注释它们。这是等效的,因为C ++会自动将inline添加到类体中定义的方法。

您的担忧似乎与生成的代码有关,您可能想知道二进制文件是否会增长太多。但是无论inline注释如何,一切都很酷,编译器查看每个函数调用并决定是内联还是生成调用。这意味着有时可以内联相同的函数(如果在循环中调用),有时也可以调用。

不同的编译器具有不同的启发式,但inline关键字对编译器的决定没有特别强烈的影响。您可以使用__forceinline__attribute__((always_inline))之类的内容来强烈要求内联函数,但即使这样,也无法保证对函数的所有调用都将被内联。相反,您可能会对__attribute__(noinline) for gcc感兴趣,它会(几乎)从不内联电话:

inline __attribute__(noinline) void log::log() // gcc
{
    std::cout << ++m_cnt << std::endl;
}

如果您想真正了解代码中发生了什么,可以使用-Winline查看inline函数何时未内联。

您还可以使用-Os-Oz优化级别来更改内部编译器阈值,以便减少内联。

您可能感兴趣的相关问题:herehere