简体   繁体   中英

Is it a good idea to implement C++ class functions outside of the class' cpp file?

Let's say I have a main.cpp, class1.cpp, class1.h, as well as other header files that won't be specified:

class1.h

#pragma once

class Class1 {
public:
  Class1(int val);
  void pubFunc();
private:
  int val1;
  void privFunc();
}

class1.cpp

#include "class1.h"

Class1::Class1(int val) {
  val1 = val;
}

void Class1:pubFunc() {
  if (val1 > 0)
    privFunc();
}

main.cpp

#include "class1.h"
#include "anotherclass.h"

AnotherClass ac;

int main() {
  Class1 c1(10);
  c1.pubFunc();
}

Class1::privFunc() {
  ac.doSomething;
}

I want Class1::pubFunc() to essentially trigger another function that can make use of AnotherClass , without including its header inside class1.cpp . This is the method that I thought of, but it feels disorganized, and I'm not too keen on putting the class instances outside of main() . The only other way I can think of doing this making Class1::pubFunc() return a string , which maps to a function, but I don't know if that's any better.

Misconception. A class in C++ does not need to have its own *.cpp file and there are pragmatical reasons to avoid having lots of tiny *.cpp files (and prefer instead having less *.cpp files, each defining several related classes and functions, so being slightly bigger).

A given translation unit (eg the *.cpp files and all the header files it is #include -ing) can (and usually does) define and declare several class -es and functions.

In practice, you code in C++ by using several standard containers or other standard C++ facilities provided by standard C++ headers , such as smart pointers from <memory> , strings from <string> , vectors from <vector> , sorting functions from <algorithm> and so on. The powerful C++ standard library is one of the reasons to code in C++ (instead of C, for instance). So you would #include perhaps several standard headers like <vector> or <map> . Standard headers are quite complex: on my Linux machine, #include <vector> generally expands to more than ten thousand of included lines (and that is one of the reasons why C++ code compiles slowly). So it is unwise (but possible) to have many small C++ files of a hundred lines each which are including some standard header, because a small yourcode.cpp file containing #include <vector> and two hundreds lines of your C++ code is expanded to much more: the compiler parses about 10000 lines of code (LOC) from <vector> and 200LOC of your code, so 10200 LOC in total.

BTW, you can ask your compiler to give the preprocessed form of your translation unit (with GCC , using g++ -C -E yourcode.cpp > yourcode.ii ) and look (with an editor or a pager) inside that yourcode.ii .

(your example is not genuine C++11 code; in practice, it should often use standard containers and some other features -smart pointers, threads, standard algorithms...- of the rich C++ standard library , but it does not)

So I recommend to have your *.cpp containing at least a thousand or two of your C++ source code lines, and of course they could define several of your related classes (and functions). In some cases, a single C++ class might be implemented in several C++ files (because that class has a lot of methods).

BTW, in your C++ classes, a lot of small functions (including member functions) are inlined and you'll define them in some of your header file.

I recommend studying the source code of several C++ free software projects for inspiration. You'll find many of them on github or elsewhere.

Your question is a consequence of an earlier questionable decision -- to use a global variable to share an instance of AnotherClass between main() and Class1 .

If you break that dependency, perhaps by using a callback, or an interface, then your need to scatter Class1 member function definitions across multiple compilation units will disappear as well.

Here's one way you might cure the dependency:

class1.h

#include <functional>

class Class1
{
public:
  Class1(int val, std::function<void(void)> callback);
  void pubFunc(void);
private:
  std::function<void(void)> do_the_thing;
  int val1;
};

class1.cpp

#include "class1.h"

Class1::Class1(int val, std::function<void(void)> callback)
   : val1(val), do_the_thing(std::move(callback))
{
}

void Class1:pubFunc(void)
{
  if (val1 > 0)
    do_the_thing();
}

main.cpp

#include "class1.h"
#include "anotherclass.h"

int main(void)
{
  AnotherClass ac;

  Class1 c1(10, std::bind(&AnotherClass::doSomething, ac));
  // can also write as     [](){ ac.doSomething(); }
  c1.pubFunc();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM