修复 C++ 中一个函数的多重定义错误

Muhammad Husnain 2023年10月12日
修复 C++ 中一个函数的多重定义错误

这篇文章是关于 C++ 中经常出现的错误的解决方法,即函数的多个定义

修复 C++ 中的 multiple definitions of a function 错误

这种错误通常是在我们试图分离函数原型和它的定义时引起的。因此,建议你将原型和定义分开放在不同的文件中,并相应地包含该文件。

参考下面的例子来理解这个问题。

示例代码(file1.cpp):

// file1.cpp
#include <iostream>
using namespace std;

class classB {
  friend void f1();

 public:
  classB(int i = 1, int j = 2) : a(i), b(j) {
    cout << "Hello from constructor\n";
  }

 private:
  int a;
  int b;
  void printfun() { cout << "a=" << a << endl << "b=" << b << endl; }
};
void f1() {  // ERROR HERE
  cout << "f1 start" << endl;
  classB tmp(3, 5);
  tmp.printfun();
  cout << "f1 end" << endl;
}

示例代码(main.cpp):

// main.cpp
#include <iostream>

#include "file1.cpp"
using namespace std;

int main() {
  cout << "calling function" << endl;
  f1();
  cout << "exit from main" << endl;
  return 0;
}

这就是在你的情况下发生的事情。由于 file1.cpp 文件中的 #includefile1.cppmain.cpp 都包含 f1() 的定义,并且链接器不知道在你的文件中使用哪一个程序并抱怨它。

解决方案是从 main.cpp 中删除包含 f1() 定义的 CPP 文件,并在单独的头文件中包含 f1() 的声明,并将其包含在 main.cpp 中。编译器将处理 f1() 的声明,而链接器将仅依赖 file1.cpp 中的 f1() 定义。

示例代码(file1.h):

// file1.h
#include <iostream>

class classB {
  friend void f1();

 public:
  classB(int i = 1, int j = 2) : a(i), b(j) {
    std::cout << "Hello from constructor\n";
  }

 private:
  int a;
  int b;
  void printfun() { std::cout << "a=" << a << endl << "b=" << b << std::endl; }
};

示例代码(file1.cpp):

// file1.cpp
#include "file1.h"
using namespace std;
void f1() {
  cout << "f1 start" << endl;
  classB tmp(5, 6);
  tmp.printfun();
  cout << "f1 end" << endl;
}

示例代码(main.cpp):

// main.cpp
#include <iostream>

#include "file1.h"
using namespace std;

int main() {
  cout << "calling function" << endl;
  f1();
  cout << "exit from main" << endl;
  return 0;
}

让我们从头文件 file1.h 开始。头文件包含所有内容的定义,如函数定义、任何结构或类定义或任何常量定义。

这个 .h 扩展名告诉编译器不要编译这个文件。它就像一个文本文件,任何人都可以阅读。

这意味着头文件是一个文档文件。如果以后有程序员想使用某些函数,只需要检查函数的原型,不需要详细介绍函数定义。

最后,模板代码也应该在头文件中。

CPP 文件现在定义了在头文件中声明的函数。这告诉编译器该文件将被编译并转换为二进制文件。

你的代码的完整性将受到保护,未经你的许可,任何人都不能修改它。这意味着这种代码分离也确保了代码文件的安全性。

这种技术背后的另一个原因是便携性。例如,你编写了一个二进制搜索代码,以后可以在许多其他程序中使用。

如果你有这些单独的函数文件,则可以在任何其他项目中轻松使用这些函数。

最后,主文件只包含主函数,并在顶部包含头文件。这个文件只包含主函数,它只调用所有函数,没有别的。

Muhammad Husnain avatar Muhammad Husnain avatar

Husnain is a professional Software Engineer and a researcher who loves to learn, build, write, and teach. Having worked various jobs in the IT industry, he especially enjoys finding ways to express complex ideas in simple ways through his content. In his free time, Husnain unwinds by thinking about tech fiction to solve problems around him.

LinkedIn

相关文章 - C++ Error