C++ programming style

I'm an old (but not too old) Java programmer, that decided to learn C++. But I have seen that much of C++ programming style, is... well, just damn ugly!

All that stuff of putting the class definition in a header file, and the methods in a different source file- Calling functions out of nowhere, instead of using methods inside classes . All that just seems... wrong!

So finally, is there any reason for me to continue with this massacre to the OOP, and anything that is good and righteous in programming, or can I just ignore that old-fashioned C++ conventions, and use my good Java programing style?

By the way I'm learning C++, because I want to do game programing.

Here is an example:

In an C++ website I found a Windows implementation:

class WinClass
{
    public:

        WinClass (WNDPROC wndProc, char const * className, HINSTANCE hInst);
        void Register ()
        {
            ::RegisterClass (&_class);
        }

    private:

        WNDCLASS _class;
};

That class is located in a header file and the constructor:

WinClass::WinClass (WNDPROC wndProc, char const * className, HINSTANCE hInst)
{
    _class.style = 0;
    _class.lpfnWndProc = wndProc;  // Window Procedure: mandatory
    _class.cbClsExtra = 0;
    _class.cbWndExtra = 0;
    _class.hInstance = hInst;           // Owner of the class: mandatory
    _class.hIcon = 0;
    _class.hCursor = ::LoadCursor (0, IDC_ARROW); // Optional
    _class.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); // Optional
    _class.lpszMenuName = 0;
    _class.lpszClassName = className;   // Mandatory
}

Is located at a .cpp source file.

What I could just do is:

class WinClass
{
    public:
        WinClass (WNDPROC wndProc, char const * className, HINSTANCE hInst)
        {
            _class.style = 0;
            _class.lpfnWndProc = wndProc;  // Window Procedure: mandatory
            _class.cbClsExtra = 0;
            _class.cbWndExtra = 0;
            _class.hInstance = hInst;           // Owner of the class: mandatory
            _class.hIcon = 0;
            _class.hCursor = ::LoadCursor (0, IDC_ARROW); // Optional
            _class.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); // Optional
            _class.lpszMenuName = 0;
            _class.lpszClassName = className;   // Mandatory
        }

        void Register ()
        {
            ::RegisterClass (&_class);
        }

    private:
        WNDCLASS _class;
};

And now the constructor is inside its class.


In addition to what others have said here, there are even more important problems:

1) Large translation units lead to longer compile times and larger object file sizes.

2) Circular dependencies! And this is the big one. And it can almost always be fixed by splitting up headers and source:

// Vehicle.h
class Wheel {
    private:
        Car& m_parent;
    public:
        Wheel( Car& p ) : m_parent( p ) {
            std::cout << "Car has " << m_parent.numWheels() << " wheels." << std::endl;
        }
};

class Car {
    private:
        std::vector< Wheel > m_wheels;
    public:
        Car() {
            for( int i=0; i<4; ++i )
                m_wheels.push_back( Wheel( *this ) );
        }

        int numWheels() {
            return m_wheels.size();
        }
}

No matter what order you put these in, one will always be lacking the definition of the other, even using forward declarations it won't work, since in the function bodies are using specifics about each class's symbol.

But if you split them up into proper .h and .cpp files and use forward declarations it will satisfy the compiler:

//Wheel.h
//-------
class Car;

class Wheel {
private:
    Car& m_parent;
public:
    Wheel( Car& p );
};

//Wheel.cpp
//---------
#include "Wheel.h"
#include "Car.h"

Wheel::Wheel( Car& p ) : m_parent( p ) {
        std::cout << "Car has " << m_parent.numWheels() << " wheels." << std::endl;
}

//Car.h
//-----
class Wheel;

class Car {
private:
    std::vector< Wheel > m_wheels;
public:
    Car();
    int numWheels();
}

//Car.cpp
//-------
#include "Car.h"
#include "Wheel.h"

Car::Car() {
        for( int i=0; i<4; ++i )
            m_wheels.push_back( Wheel( *this ) );
}

int Car::numWheels() {
        return m_wheels.size();
}

Now the code that actually has to know specifics about the second class can just include the header file which doesn't need to know specifics about the first class.

Headers just provide the declarations while source files provide the definitions. Or another way to say it: Headers tell you what is there (what symbols are valid to use) and source tells the compiler what the symbols actually do. In C++ you don't need anything more than a valid symbol to begin using whatever it is.

Trust that C++ has a reason for this idiom, because if you don't you will make a lot of headaches for yourself down the line. I know :/


When the code builds, the C++ preprocessor builds a translation unit. It starts with a .cpp file, parses the #includes grabbing the text from the headers, and generates one great big text file with all the headers and the .cpp code. Then this translation unit gets compiled into code that will run on the platform you're targeting. Each translation unit ends up as one object file.

So, .h files get included in multiple translation units, and a .cpp file just gets included in one.

If .h files contain lots of stuff (including implementation), then the translation units would be correspondingly bigger. Compile times would increase, and when you change anything in a header... every translation unit that uses it would need to be recompiled.

So.. minimizing stuff in .h files drastically improves compile time. You can edit a .cpp file to change a function, and only that one translation unit needs to be rebuilt.

To complete the story on compiling...
Once all the translation units are build into object files (native binary code for you platform). The linker does its job, and stitches them together into you .exe, .dll or .lib file. A .lib file can be linked into another build so it can be reused in more than one .exe or .dll.

I suppose the Java compilation model is more advanced, and the implications of where you put your code have less meaning.


.h and .cpp files often separate declarations from definitions, and there is some kind of order here, and conceptual encapsulation. headers have the 'what', implementation files have the 'how'.

I find having everything in one file in java to be disorganized. So, each to their own.

C++ conventions and idioms all have well thought out reasoning, just like any other language does for the idioms its community adopts.

I think it's best to java (as a verb) when you write Java, and to C++ when you C++! You'll appreciate why with experience of the language. Same as switching to any new language.

链接地址: http://www.djcxy.com/p/85408.html

上一篇: 您如何减少编译时间以及Visual C ++项目(本机C ++)的链接时间?

下一篇: C ++编程风格