Separating C++ Class Code into Multiple Files, what are the rules?

后端 未结 3 997
孤独总比滥情好
孤独总比滥情好 2021-01-31 17:15

Thinking Time - Why do you want to split your file anyway?

As the title suggests, the end problem I have is multiple definition linker errors. I have actually fixed the

相关标签:
3条回答
  • 2021-01-31 17:58

    Do standards like this exist in industry?

    Yes. Then again, coding standards that are rather different from the ones you expressed can also be found in industry. You are talking about coding standards, after all, and coding standards range from good to bad to ugly.

    Will the standard I came up with work in all cases?

    Absolutely not. For example,

    template <typename T> class Foo {
    public:
       void some_method (T& arg);
    ...
    };
    

    Here, the definition of class template Foo doesn't know a thing about that template parameter T. What if, for some class template, the definitions of the methods vary depending on the template parameters? Your rule #2 just doesn't work here.

    Another example: What if the corresponding source file is huge, a thousand lines long or longer? At times it makes sense to provide the implementation in multiple source files. Some standards go to the extreme of dictating one function per file (personal opinion: Yech!).

    At the other extreme of a thousand-plus line long source file is a class that has no source files. The entire implementation is in the header. There's a lot to be said for header-only implementations. If nothing else, it simplifies, sometimes significantly, the linking problem.

    0 讨论(0)
  • 2021-01-31 18:02

    The main reason to separate interface from implementation is so that you don't have to recompile all of your code when something in the implementation changes; you only have to recompile the source files that changed.

    As for "Declare the class (template or otherwise)", a template is not a class. A template is a pattern for creating classes. More important, though, you define a class or a template in a header. The class definition includes declarations of its member functions, and non-inine member functions are defined in one or more source files. Inline member functions and all template functions should be defined in the header, by whatever combination of direct definitions and #include directives you prefer.

    0 讨论(0)
  • 2021-01-31 18:06

    Your three points sound about right. That's the standard way to do things (although I've not seen .tpp extension before, usually it's .inl), although personally I just put inline functions at the bottom of header files rather than in a separate file.

    Here is how I arrange my files. I omit the forward declare file for simple classes.

    myclass-fwd.h

    #pragma once
    
    namespace NS
    {
    class MyClass;
    }
    

    myclass.h

    #pragma once
    #include "headers-needed-by-header"
    #include "myclass-fwd.h"
    
    namespace NS
    {
    class MyClass
    {
        ..
    };
    }
    

    myclass.cpp

    #include "headers-needed-by-source"
    #include "myclass.h"
    
    namespace
        {
        void LocalFunc();
    }
    
    NS::MyClass::...
    

    Replace pragma with header guards according to preference..

    The reason for this approach is to reduce header dependencies, which slow down compile times in large projects. If you didn't know, you can forward declare a class to use as a pointer or reference. The full declaration is only needed when you construct, create or use members of the class.

    This means another class which uses the class (takes parameters by pointer/reference) only has to include the fwd header in its own header. The full header is then included in the second class's source file. This greatly reduces the amount of unneeded rubbish you get when pulling in a big header, which pulls in another big header, which pulls in another...

    The next tip is the unnamed namespace (sometimes called anonymous namespace). This can only appear in a source file and it is like a hidden namespace only visible to that file. You can place local functions, classes etc here which are only used by the the source file. This prevents name clashes if you create something with the same name in two different files. (Two local function F for example, may give linker errors).

    0 讨论(0)
提交回复
热议问题