【问题标题】:Two files using each other funtions - how to solve it?两个文件互相使用功能 - 如何解决?
【发布时间】:2019-04-05 01:58:17
【问题描述】:

我有两个带有源文件的头文件,比如说file1.hfile1.ccfile2.hfile2.cc。他们使用彼此的功能,例如:

file1.h:

void test1();

file2.h:

void test2();

file1.cc:

#include "file1.h"
#include "file2.h"

void test1() {
  do_something();
  test2();
}

file2.cc:

#include "file1.h"
#include "file2.h"

void test2() {
  do_something_else();
  test1();
}

我得到了问题,依赖是相互的,我们不能编译一个文件而不编译另一个文件。如何解决这个问题?

【问题讨论】:

  • 你有一个更大的问题,其中一个症状是,如果你能够编译代码,调用任何一个函数都会导致无休止的来回调用序列,直到你的系统用完一些资源——可能是堆栈内存。我想说你需要更多地思考为什么你想要两个以这种方式相互依赖的函数。
  • 除了你没有声明你的代码应该编译的do_something函数。
  • @Tim 在解析器等应用中相互递归是很常见的事情。
  • 问题在于你如何链接文件,而不是编译它们。
  • 你显示的头文件和源文件都很好;这正是你应该做的。这就是为什么人们(正确地)说问题在于您如何构建应用程序的原因。您需要编译并链接包含main 的源文件以及您在此处显示的两个源文件。一种可能性是clang++ main.cpp file1.cpp file2.cpp

标签: c++ header include linkage


【解决方案1】:
  1. 修改文件以删除双重递归。
  2. 使用一些代码来防止重复包含您的 .h 文件(我在 .h 文件的顶部使用了 #pragma once
  3. (可选)添加 main.cpp 以调用函数
  4. 为 do_something() 提供代码
  5. 使用 . g++ *.cpp -o main

好问题!

这里是文件:

// main.cpp
//

#include <iostream>

#include "file1.h"
#include "file2.h"

int main() {

    test2();
    std::cout << "Hello, World!" << std::endl;
    return 0;
}

// file1.cpp

#include "file1.h"
#include "file2.h"
#include <iostream>

void do_something() {
    std::cout << "Just hit do_something" << std::endl;
}
void test1() {
    do_something();
//    test2();  // Do not use double recursion.
}

// file1.h

#pragma once

void do_something();
void test1();

// file2.cpp

#include "file1.h"
#include "file2.h"

void test2() {
    do_something();
    test1();
}

// file2.h

#pragma once

void test2();

【讨论】:

  • 很好,我正要写这样的东西,但你打败了我!
  • 您的第 1 点和第 2 点是很好的通用建议,但它们没有解决问题,即明确管理递归。删除递归当然会使递归问题消失。
  • JohnHill 提供了很好的回应。我提供了一个工作示例。我已经在有和没有递归的情况下对其进行了测试。两者都编译。所以,我已经回答了这个问题。在没有退出条件的情况下调用递归函数是错误的,所以我把它拿出来了。我也同意@JakeFreeman 并使用了 .h 警卫。关键可能是编译器命令。 OP 没有提供最小可编译示例。我提供了一个任何人都可以玩的完整示例。不知道为什么在我提供了确切要求的内容后我会遭到反对。
【解决方案2】:

最好的答案是不要这样设计你的代码!这会引入一个“circular dependency”,它会立即让你的代码变得脆弱。此外,您编写示例的方式描述了一个双递归函数(A 调用 B 调用 A),并且由于没有终止条件,因此是无限的!如您所见,这可能会导致一些非常难以控制的情况。

让我们暂时放弃良好的工程实践。您如何描述头文件和源文件就足够了,可以使用以下命令构建:

g++ file1.cc file2.cc -o libCoupledRecursiveExample.so

这就是事情变得困难的地方:仅通过构建指令,您实际上无法检测到依赖关系!好的静态代码检查器可以检测到这些情况并向您发出警告,但是当您使用惰性编译器(例如没有标志的g++)时,很容易被这样的不会产生任何警告的代码偷偷摸摸。

【讨论】:

  • 您可以使用 #pragma 一次或包含守卫,而不是使用不同的编码方式
  • 我认为双重递归是这里真正的问题,正如@JohnHill 所描述的那样。仅当 .h 文件将包含另一个 .h 文件时,才需要 #pragma once (我包含在我的答案中)。 OP 并未声称要这样做。
猜你喜欢
  • 2019-02-20
  • 1970-01-01
  • 2012-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-13
  • 1970-01-01
  • 2015-11-21
相关资源
最近更新 更多