【问题标题】:C++ compile multiple files with same function nameC ++编译具有相同函数名的多个文件
【发布时间】:2016-06-04 09:34:02
【问题描述】:

在 printNumbers.h 文件中

//Write a function getNumber() and put your favourite number inside! 
//I will then compile the program and print everyone's favourite number!
int getNumber(void);

如果我想继续打印出三个人最喜欢的数字

int main() {
    int counter = 0;
    while(counter < 9999) {
         if(counter % 3 == 0) {
             //Print out the first person's number
             printf("My number is %d\n", getNumber();
         } else if (counter % 3 == 1) {
             //Print out the second person's number
             printf("My number is %d\n", getNumber();
         } else {
             //Print out the third person's number
             printf("My number is %d\n", getNumber();
         }

         //Keep printing everyone's numbers until counter reaches 9999

         counter++;
    }
    return 0;
}

3 个人给了我他们编写的 C++ 文件,我将每个文件重命名为 A.cpp B.cpp C.cpp。它可能是随机顺序的,所以他们不知道他们的文件最终是 A B 还是 C

他们可以编写的 c++ 文件示例

int getNumber() {
    //Each person can write their own function to return whatever number they want
    int myNumber = 1;
    return myNumber;
}

无论如何,我要编译程序并使用 A.cpp 中的 getNumber() 进行第一次调用,使用 B.cpp 进行第二次调用,使用 C.cpp 进行第三次调用,然后重复.

我可以在 while 循环中命名函数名称 getNumber1() getNumber2() getNumber3() 并更改三个 C++ 文件中的函数名称,但是当有人编写 getNumber() 函数时,他们不知道它是否会结束最多是 A B 或 C。每个人的 getNumber() 函数都应该称为 getNumber()。

.

编辑:很多人都在建议命名空间。我无法控制 .h 文件和人们获得的 ADT,因此他们编写的程序不会使用命名空间。还有很多人可能会向我提交 C++ 文件,我必须将它们随机分组为 3 个组(因为我的程序只能打印 3 个人的数字),所以他们不知道要使用什么命名空间。 .

编辑: 一些人建议修改 .h 文件或人们编写的程序。我们都得到了 .h 文件,我们无法更改它。我们将文件(如示例)提交给学校,他们能够完成我的主要功能(我不知道他们是如何做到的)。我的 main 函数将允许用户在提交之前更好地测试他们的 getNumber() 函数,因此它是一个独立于学校的程序,用户可以选择使用。

如果任何事情看起来令人困惑或不清楚,请向我提问以澄清我的问题!

谢谢。

【问题讨论】:

  • 这种东西不是命名空间的用途吗?
  • 不,没有。您不能链接到他们所有的翻译单元并且对同一函数有多个定义。
  • 使用 -DgetNumber=getNumberXXX 编译,每个文件使用不同的 XXX...
  • 与其重复编辑问题以揭示更多约束,不如逐字包含整个作业。
  • @MarkPlotnick 嘿,马克,没有分配。这只是一个附带项目。主要任务是写一个 getNumber() 函数,然后学校会一起编译 3 个人的 getNumber() 函数并重复打印他们的数字。我正在做的是另一个类似的程序,学校将如何打印 3 个人的数字,但包括更多的东西来帮助人们测试他们的功能

标签: c++ c


【解决方案1】:

假设您正在获取他们不想更改的 cpp 文件,而不是编译和链接它们,您可以将它们包含在您的 cpp 中,就像这样

namespace A {
  #include "A.cpp"
}
namespace B {
  #include "B.cpp"
}
namespace C {
  #include "C.cpp"
}

int main ()
{
  A::getNumber();
  B::getNumber();
  C::getNumber();
}

【讨论】:

  • A.cpp B.cpp C.cpp #includes .h 以便 ADT 工作。我只是用你的方法编译它。很多重载函数错误:对重载函数的模棱两可的调用,并且没有一个曾经加载过的函数需要 X 个参数
  • .h 文件是否包含保护?
  • 哦,好吧,他们没有包括警卫。我从每个 .cpp 文件中删除了所有 #include .h 并且它工作了。虽然最好保持 cpp 文件未经编辑,但删除 #includes 似乎不是很多工作。所以这是一个非常好的解决方案。谢谢!!
  • 我所做的一种解决方法是将#included .h 文件设为空白,这样它们就不会包含它们,并在我的主 cpp 文件中包含一个重命名的文件,因此我不再需要删除#includes 来自每个人的 cpp 文件!
【解决方案2】:

没有办法将具有相同名称和参数列表的多个不同函数放入全局命名空间,即使来自不同的翻译单元。

但是,C++ 允许您使用 命名空间 来区分同名函数:

a.cpp

namespace a {
    int getNumber() {
        return 1;
    }
}

b.cpp

namespace b {
    int getNumber() {
        return 205;
    }
}

调用者可以通过上下文解析运算符区分getNumber函数:

 if(counter % 3 == 0) {
     //Print out the first person's number
     printf("My number is %d\n", a::getNumber();
 } else if (counter % 3 == 1) {
     //Print out the second person's number
     printf("My number is %d\n", b::getNumber();
 } else {
     //Print out the third person's number
     printf("My number is %d\n", c::getNumber();
 }

【讨论】:

  • 我无法控制 .h 文件和 ADT,因此我必须让每个人都将命名空间放入其中,以使其也能与我的程序一起使用。我想这很好,但对他们来说工作量要多一些。
【解决方案3】:

如果您需要选择在运行时调用的函数,您可以这样做。

不要在头文件中给出函数原型,而是创建一个函数指针数组:

typedef void (*GetNumberType)();
extern GetNumberType functions[5];

在 main.cpp 中:

GetNumberType functions[5];

在每个 A、B、C .cpp 中:

class Register
{
  Register()
  {
    int i =0;
    // find a place to put the function in
    while(functions[i]) i++;
    functions[i] = &getNumber;
  }
};

Register r;

void getNumber()
{
...
}

现在您可以遍历 main.cpp 中的 functions 并调用它们。

【讨论】:

  • 在我的编辑中:我写的 .h 文件是提供给每个人的,我无法更改它。神奇的是,如果他们屈服于魔法人,他们可以让我的 main() 函数工作。
  • 我正在编写一个稍微不同的程序,人们可以使用它来帮助他们更好地测试他们的功能。程序与人们拥有的魔法不同,但我不知道他们是如何让它发挥作用的
  • 如果您已经给出了标题,那么您无能为力。或者,您可以要求它们编译成共享对象(SO、DLL),然后使用动态链接器函数来处理这种情况。
【解决方案4】:

您需要将每个用户的 c++ 文件编译成独立的可执行文件/DLL/可调用代码,然后从您的主程序中调用这些以获取数字。

在所有情况下都使用相同的标题,您别无选择。

【讨论】:

  • 这看起来很有希望! (但我对这一切都不是很擅长,所以我不知道该怎么做)您能否对此进行扩展以指导我如何将它们编译为独立的可执行文件/DLL/可调用代码以及如何调用编译好的程序?
  • @Friedpanseller:你在哪个平台上? - Windows、Linux、Mac?什么想法? - MSVS,...
  • Windows 平台。稍后我将处理 Linux。最终我的程序将需要在 Linux 上工作,但我现在正试图让 Windows 工作。
  • 自从我上次使用 Windows 以来的时间很长:查看文档如何创建和使用 dll - 这很简单,可以在函数周围放置导出 (IIRC) 包装器,可以像 #include 一样简单导出包装器中的 c++ 文件在模板文件中,然后编译(你在学校&需要学习这些东西;)
  • @Friedpanseller:如果你走这条路,你也可以在代码周围放置命名空间包装器——这会大大简化事情
【解决方案5】:

在 Windows 上,您可以将每个文件编译为 dll,然后动态加载该函数。

【讨论】:

    【解决方案6】:

    无论如何,我要编译程序并使用 A.cpp 中的 getNumber() 进行第一次调用,使用 B.cpp 进行第二次调用,使用 C.cpp 进行第三次调用,然后重复。

    不,没有。函数int getNumber() 只能有一个定义。

    如果你想把它们编译成一个程序,那么要么

    1. 编写源文件的每个人都必须使用唯一的名称(可能使用命名空间,或者只是使用不同的函数名称),或者如果这不是一个选项,那么
    2. (或负责编译和链接文件的人)必须修改您(或他们)收到的源文件,以便每个函数都有一个唯一的名称。

    选项 2. 可以使用预处理自动化。 c 预处理器可能会实现您想要做的事情,但另一方面,编写您自己的程序来处理文件可能更简单。

    另一种方法可能是使用包装器(这种修改正好在 c 预处理器的小巷)来扩充每个单独的源文件,它定义了 main 函数,它只调用该函数一次。然后将每个编译为单独的程序。然后编写将其他程序作为子进程生成的主程序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-04
      • 1970-01-01
      • 1970-01-01
      • 2018-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多