没有.cpp文件的C ++类?

时间:2014-03-18 12:15:20

标签: c++ class templates header-files

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

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

所以我使用模板来摆脱链接器投诉:

// log.hpp file
template<typename T>
class log_t {
private:
    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;

然后我可以在多个log文件中使用.cpp类,而不会有链接器投诉。

这种方法有什么根本原因吗?

编辑:即使我使用此方法,会员功能会成为内联吗?

3 个答案:

答案 0 :(得分:5)

如果某个课程不需要成为模板,请不要将其作为模板,只是为了&#34;摆脱链接器的抱怨&#34; 。只需使用适当的编码技术,例如提供成员函数的内联定义:

// log.hpp file

#pragma once

#include <iostream> // For std::cout, std::endl

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

// Note "inline" here:
inline log::log() {
    std::cout << ++m_cnt << std::endl;
}

如果您在课程定义中提供了函数正文,则无需指定关键字inline

// log.hpp file

#pragma once

#include <iostream> // For std::cout, std::endl

class log {
private:
    static int m_cnt = 0;
public:
    // Function body inserted here (no need for "inline"):
    log() {
        std::cout << ++m_cnt << std::endl;        
    }
};

答案 1 :(得分:3)

如果您希望在标题中定义函数(包含在多个源文件中,这会导致您的案例中出现多个定义),您应该创建函数inline

2个选项:

  • 隐式inline - 不要将功能定义
  • 分开
  • 明确inline - 在定义前面手动添加inline关键字

使用template只是为了“解决”这个错误并不是一个好主意。仅在需要时使用模板。

答案 2 :(得分:1)

What's wrong with this Method ? Is there something fundamentally wrong with this method ?

不,这种方法没有问题。您需要做的是通过以下方式遵守One Definition Rule

  1. 通过将定义放在声明中或在每个函数声明之前放置inline关键字来使函数定义内联。这是为了避免多个翻译单元中的多个定义(cpp文件简化一点)
  2. 在头文件中添加包含警戒。这是为了避免多次包含在同一翻译单元中。
  3. 实际上,此方法是template工作的唯一方法。您不能将模板定义放在cpp文件中,并希望它能够正常工作,因为C++编译器需要定义来实例化模板。使用template不是此方法的解决方案,但是如果您希望编译代码,则需要您仅使用此方法。