How to define a member struct in a separate file for C++

Viewed 99

I am trying to define a member struct of a class in a separate file. however, I not sure what is the correct way to implement it.

Below is what I have tried. in code1.cpp is the main source code. I would like to put the definition of the member struct, Mid, to a separate file, code2.cpp. However, in order for code2.cpp know the struct is part of TestCls, I import code1.cpp there and added the guards. I know this is not going to work but I am not sure how to make it work. Thanks

code1.cpp:

#include <iostream>
#include "code2.cpp"


class TestCls {
 public:
  struct Mid;
};

int main() {
  TestCls::Mid mid1;
  std::cout << mid1.a << std::endl;
}

code2.cpp

#ifndef XXX
#define XXX


#include <iostream>
#include <sys/dtrace.h>
#include "code1.cpp"

struct TestCls::Mid {
  int a = 0;
};

#endif //XXX
1 Answers
  1. Don't include cpp files. Only include header files. While headers files can technically have any (or no) suffix, using source file suffix may end up confusing a build system or compiler to think that it is supposed to be compiled, which you don't want to do with a header. .h or .hpp and few others are commonly used suffixes for headers.

  2. Your code2.cpp includes code1.cpp and code1.cpp includes code2.cpp. Don't have recursive includes like this. While the include guard prevents infinite recursion, this can easily break in some cases.

For a small program like this, as an exercise, I recommend that you first write it entirely into a single file. For example, following would be correct:

class TestCls {
 public:
  struct Mid;
};

struct TestCls::Mid {
  int a = 0;
};

#include <iostream>

int main() {
  TestCls::Mid mid1;
  std::cout << mid1.a << std::endl;
}

Now, you can slice the file into multiple ones while keeping the order.

// TestCls.hpp
#pragma once
class TestCls {
 public:
  struct Mid;
};

// TestClsMid.hpp
#pragma once
#include "TestCls.hpp"
struct TestCls::Mid {
  int a = 0;
};

// main.cpp
#include "TestCls.hpp"
#include "TestClsMid.hpp"

#include <iostream>

int main() {
  TestCls::Mid mid1;
  std::cout << mid1.a << std::endl;
}

I used #pragma once for simplicity, buy you can opt for macro guards if you so prefer.

That said, I recommend to reconsider whehter there is any advantage in not defining TestCls::Mid in TestCls.hpp.

Related