-3

I have two headers with source files, lets say file1.h, file1.cc and file2.h, file2.cc. They use each others functions, for example:

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();
}

I get the problem, the dependancy is mutual and we cant compile one file without having another compiled. How to solve this problem?

Shrikanth N
  • 652
  • 3
  • 17
Bluerain
  • 9
  • 4
  • What happens when you try to compile? – Christian Gibbons Oct 31 '18 at 20:09
  • 2
    You have a bigger problem, one symptom of which is that, if you were able to compile the code, calling either function would result in an unending sequence of calls back and forth until your system ran out of some resource—probably stack memory. I'd say you need to think more about why you want two functions that depend on one another in that way. – Tim Randall Oct 31 '18 at 20:09
  • 3
    Apart from the fact you haven't declared the `do_something` functions your code should compile. –  Oct 31 '18 at 20:10
  • 1
    @Tim Mutual recursion in applications such as parsers is a common thing. –  Oct 31 '18 at 20:11
  • I said it wrong, the linkage doesnt see the reference to one of functions, when I use both of them in main. Is it because of some other problem? – Bluerain Oct 31 '18 at 20:13
  • @Neil I accept that. I'm trying to read between the lines here, and assuming that the OP has greatly simplified their code in order to post here (which I appreciate). So I'm wondering what the real problem is. It certainly should be possible to declare the functions, and compile and run the code. – Tim Randall Oct 31 '18 at 20:13
  • Show us a `main` that exhibits the problem. –  Oct 31 '18 at 20:14
  • @Bluerain that sounds like a problem setting up your build environment. Project settings, perhaps. Are both the CC files part of the program you're building? – Tim Randall Oct 31 '18 at 20:15
  • how are you compiling? what compiler and what options? – lostbard Oct 31 '18 at 20:18
  • 1
    The problem is with how you're linking the files, not with compiling them. – Barmar Oct 31 '18 at 20:18
  • Show us the full error – Jake Freeman Oct 31 '18 at 20:19
  • 1
    The headers and source files you've shown are just fine; that's exactly how you should do it. That's why people are saying (correctly) that the problem is in how you're building your application. You need to compile and link the source file that contains `main` and the two source files that you've shown here. One possibility is `clang++ main.cpp file1.cpp file2.cpp`. – Pete Becker Oct 31 '18 at 20:19
  • You should be able to compile the source code to object code (`.cc` to `.o`) without problem. When you link, you need to specify both `file1.o` and `file2.o` on the link line, plus the object file(s) that provide the `do_something()` and `do_something_else()` functions, and the file that provides `main()`. If you have `file1.o` in library `lib1.a` and `file2.o` in library `lib2.a`, then you have mutual dependencies between two libraries, which is more complex to solve unless you do the obvious and create one library for both sets of object files. – Jonathan Leffler Oct 31 '18 at 20:21

2 Answers2

1
  1. Modify the files to remove the double recursion.
  2. Use some code to prevent double inclusion of your .h files (I have used #pragma once at the top of the .h files)
  3. optionally, add a main.cpp to call the functions
  4. provide code for do_something()
  5. compile using . g++ *.cpp -o main

Great question!

Here are the files:

// 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();
Gardener
  • 2,591
  • 1
  • 13
  • 22
  • 1
    Nice I was going to write something like that but you beat me! – Jake Freeman Oct 31 '18 at 21:13
  • Your points 1 and 2 are good generic advice, but they do not address the question, which is **explicitly** about managing the recursion. Removing the recursion of course makes the recursion problem go away. – Pete Becker Oct 31 '18 at 21:42
  • JohnHill provided a good response. I provided a working example. I have tested it with and without the recursion. Both compile. So, I have answered the question. Calling a recursive function without an exit condition is wrong, so I took that out. I also agree with @JakeFreeman and have used a .h guard. The key is likely the compiler command. The OP has not provided a Minimal Compilable example. I have provided a complete example that anyone can play with. Not sure why I would get a downvote when I have provided exactly what was requested. – Gardener Oct 31 '18 at 21:56
-2

The best answer is don't design your code like that! This introduces a "circular dependency," which immediately makes your code fragile. Additionally, the way you have your example written describes a double-recursive function (A calls B which calls A), and since there is no terminating condition, is unbounded! As you can see, this can lead to some very unmanageable circumstances.

Let's forego good engineering practices for a while. How you described both headers & source files is adequate and can be built with the following command:

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

This is where things become difficult: through the build instructions alone, you can't actually detect the dependency! Good static code checkers can detect these circumstances and warn you, but when you use a lazy compiler (like g++ without flags), it's easy to sneak by code like this that won't generate any warnings.

jhill515
  • 894
  • 8
  • 26
  • You could use #pragma once or include guards rather than coding differently – Jake Freeman Oct 31 '18 at 21:00
  • 1
    I think that the double recursion is the real issue here as @JohnHill has described. The #pragma once (which I included in my answer) is only necessary if a .h file will include another .h file. The OP did not claim to be doing that. – Gardener Oct 31 '18 at 21:06