如何在c++中重用函数(如isPrime、isEven、isPalindome)

How to reuse functions (such as isPrime, isEven, isPalindrome) in c++

本文关键字:isPrime isEven isPalindome c++ 函数      更新时间:2023-10-16

我很难找到重用常见自定义函数(如isPrime、isEven等)的解决方案。我知道我会反复重用它们,但我确实希望避免在每个.cpp文件中一次又一次地编写它们。我研究过使用头文件来包含所有这些函数,但我也听到了这样的评论,即该函数也将与头中的其他函数一起编译。因此,随着自定义函数数量的增加,编译时间也会变长。

此外,我想避免添加许多单独的文件,如isPrime.cpp、isEven.cpp等。

我应该如何有效地重用这些功能?请展示如何组织每个文件的简单模板。

谢谢。

大约有四件事是"显而易见"的解决方案。可能还有其他人。

按照"复杂性"的顺序:

  1. 将所有函数作为内联函数添加到标头中。如果函数真的很小,这是可以的,但一旦它们变得足够大,这就不是一个好的解决方案(因为函数很可能会在同一个可执行文件中多次复制)。

  2. 制作一个"functions.cpp",其中包含一束函数(适当地选择为属于一起),并在"functions.h"中声明它们——现在您只需要再链接一个文件。缺点是"functions.cpp"中的所有函数都包含在您的最终可执行文件中,无论它们是否实际使用(除非编译器非常聪明,可以"杀死"死函数——大多数编译器都不会这样做)。

  3. 制作一个库。在这种情况下,每个函数需要一个源文件,这些文件被编译并构建到一个库文件functions.a或functions.lib中。同样,您需要一个(或多个)头文件来声明您的函数,然后与库链接以将这些函数包含到可执行文件中。当链接器构建最终可执行文件时,可执行文件"需要"的每个函数都来自库,但其他不"需要"函数将不属于可执行文件的一部分。

  4. 创建共享库。这类似于构建库,只是在构建函数时将创建一个单独的"可执行"共享库文件(.dll、.dynlib或.so),而不是将函数的代码包含在可执行文件中。当你使用共享库时,你仍然需要给链接器命令一个"库",但可执行文件只有一个知道如何调用共享库代码的"stub"(或"thunk")。当你有像coutprintf这样几乎每个C++程序都使用的东西,并且一台机器上有成百上千个程序时,这真的很有用,因为所有这些程序都使用相同的printfcout代码,而不是每个程序都有一个副本。

如果你认为在命令行中添加2-3个文件是一项艰巨的工作,我建议你不要使用LLVM。以下是我为构建编译器而添加的库(幸运的是,有一个工具可以自动做到这一点):

-lLLVMLTO-lLLVMObjCARCOpts-lLLVMLinker-lLLVMipo-lLLVMVectorize-lLLVMBitWriter-lLLVMIRReader-lLLVMSmParser-lLLVM TableGen-lLLVMDebugInfo-lLLVMOption-lLLVMX86分解器-lLLVMX86AsmParser-lLLVMX86CodeGen-lLLVM SelectionDAG-lLLVMAsmPrinter-lLLVMMCParser-lLLVMX86Desc-lLLVMx86 Info-lLLVM X86AsmPrinter-lLLVMX6Utils-lLLVMJIT-lLLVMLineEditor-lLLVMMCDisassembler-lLLVMInstrumentation-lLLVMInterpriser-lLLVMCodeGen-lLLVMScalarOpts-lLLVMInstCombine-lLLVMTransformUtils-lLLVMipa-lLLVMAnalysis-lLLVMProfileData-lLLVMMCJIT-lLLVMTarget-lLLVMRuntimeDyld-lLLVMExecutionEngine-lLLVMMC-lLLVMObject-lLLVMBitReader-lLLVMCore-lLLVMSupport

您可以有一个仅包含标头的文件,该文件包含函数的定义和声明(例如functions.hpp),并且在使用函数时(与#include "functions.hpp"一起)都包含该文件:

// functions.hpp
void func() { … }
// main.cpp
#include "functions.hpp"
int main() {
    func();
}

否则,您可以有一个头文件(例如functions.hpp)和一个文件(例如,function.cpp),在头文件中定义函数签名。

// functions.hpp
void func();
// functions.cpp
#include "functions.hpp"
void func() { … }
// main.cpp
#include "functions.hpp"
int main() {
    func();
}

在后者中,您必须编译functions.cpp并将对象文件与main.cpp链接起来。

通常的方法是在头文件中声明方法,然后在另一个头文件中定义它们。例如,在common.hpp中,您可以放置:

bool isPrime(int number);
bool isEven(int number);

然后在common.cpp里面你可以放:

bool isPrime(int number) { ... }
bool isEven(int number) { ... }

然后#include "common.hpp"可以访问这些函数。请注意,如果不使用include保护,同一方法的多个声明可能会遇到问题。

在头文件中声明"#pragma once"也是一个好主意。这样,如果您的头文件包含在另一个头文件中,并且第三个文件包含第二个头文件,但也包含第一个头文件时,您将避免多次包含。如果您没有使用Visual Studio,那么请在#ifndef块:之间写入头文件内容

#ifndef HEADER_FILE
#define HEADER_FILE
//your header file contents go here
#endif
// ------------------------
// utilities.h
bool isPrime( int );
bool isEven( int );
// ------------------------
// utilities.cpp
#include utilities.h
bool isPrime( int a ){ ... }
bool isEvent( int a ){ ... }
// ------------------------
// other.cpp
#include utilities.h
int main()
{
     isPrime( 2 );
     return 0;
}