在标题,内联函数和代码中分离C ++代码时出现问题

时间:2010-03-29 17:57:59

标签: c++

我有最简单的代码,我想在三个文件中分开:

  • 头文件:类和结构声明。根本没有实现。
  • 内联函数文件:在标题中实现内联方法。
  • 代码文件:用于更复杂实现的普通C ++代码。

当我即将实现operator[]方法时,我无法编译它。这是一个显示相同问题的最小示例:

标题(myclass.h):

#ifndef _MYCLASS_H_
#define _MYCLASS_H_

class MyClass
{
 public:
  MyClass(const int n);
  virtual ~MyClass();

  double& operator[](const int i);
  double  operator[](const int i) const;

  void someBigMethod();

 private:
  double* arr;

};

#endif /* _MYCLASS_H_ */

内联函数(myclass-inl.h):

#include "myclass.h"

inline double& MyClass::operator[](const int i) {
  return arr[i];
}

inline double MyClass::operator[](const int i) const {
  return arr[i];
}

代码(myclass.cpp):

#include "myclass.h"
#include "myclass-inl.h"
#include <iostream>

inline MyClass::MyClass(const int n) {
  arr = new double[n];
}

inline MyClass::~MyClass() {
  delete[] arr;
}

void MyClass::someBigMethod() {
  std::cout << "Hello big method that is not inlined" << std::endl;
}

最后,主要测试一切:

#include "myclass.h"
#include <iostream>

using namespace std;


int main(int argc, char *argv[]) {
  MyClass m(123);
  double x = m[1];
  m[1] = 1234;
  cout << "m[1]=" << m[1] << endl;
  x = x + 1;
  return 0;
}

void nothing() {
  cout << "hello world" << endl;
}

当我编译它时,它说:

main.cpp:(.text+0x1b): undefined reference to 'MyClass::MyClass(int)'
main.cpp:(.text+0x2f): undefined reference to 'MyClass::operator[](int)'
main.cpp:(.text+0x49): undefined reference to 'MyClass::operator[](int)'
main.cpp:(.text+0x65): undefined reference to 'MyClass::operator[](int)'

但是,当我将main方法移动到MyClass.cpp文件时,它可以正常工作。你能帮助我发现问题吗?

谢谢。

4 个答案:

答案 0 :(得分:6)

用于测试设置的主程序文件不包含带有内联成员函数的头文件。由于函数是内联函数,因此它们不包含在从myclass.cpp生成的目标文件中。

内联函数不可用于编译器,因此它认为调用是外部的;但它们也不可用于链接器,因为它们不会在其他地方生成独立定义。

如果您希望函数内联,只需将它们放在myclass.h

答案 1 :(得分:3)

您必须在头文件中定义内联函数,而不是在不同的编译单元中。否则,编译器如何内联它们呢?当编译器看到一个应该是内联函数的调用时,它必须知道它的定义,因此它可以内联它而不是标记对链接器的调用。

我可以提供的最佳解决方案是从这些功能中完全删除内联关键字。仅当您具有支持决策的具体分析器编号时,或者当函数体为零到一行代码时,才内联函数。

答案 2 :(得分:0)

您需要在main.cpp中包含myclass-inl.h

不推荐在三个文件中拆分代码。

答案 3 :(得分:-2)

问题在于链接。当你链接可执行文件时,你包括myclass.o?你也需要编译它。