When declaring a class, start with public
members, then
protected
, and last private
members. Inside these groups,
you are invited to group by category, i.e., methods, types, and members
that are related should be grouped together.
Rationale: People reading your class are interested in its interface
(that is, its public
part). private
members should not
even be visible in the class declaration (but of course, it is mandatory
that they be there for the compiler), and therefore they should be
“hidden” from the reader.
This is an example of what should not be done:
class Foo { public: Foo (std::string, int); virtual ~Foo (); private: typedef std::string string_type; public: std::string bar_get () const; void bar_set (std::string); private: string_type bar_; public: int baz_get () const; void baz_set (int); private: int baz_; }
instead, write:
class Foo { public: Foo (std::string, int); virtual ~Foo (); std::string bar_get () const; void bar_set (std::string); int baz_get () const; void baz_set (int); private: typedef std::string string_type; string_type bar_; int baz_; }
and add useful Doxygen comments.
class Derived: public Base { // ... }; /// Object function to compare two Temp*. struct temp_ptr_less: public std::binary_function<const Temp*, const Temp*, bool> { bool operator() (const Temp* s1, const Temp* s2) const; };
virtual
in subclass declarations.
If a method was once declared virtual
, it remains virtual.
Nevertheless, as an extra bit of documentation to your fellow
developers, repeat this virtual
:
class Base { public: // ... virtual foo (); }; class Derived: public Base { public: // ... virtual foo (); };
std::list<int> l; std::pair<std::list<int>, int> p;
with a space after the comma, and of course between two closing >:
std::list<std::list<int> > ls;
These rules apply for casts:
// Come on baby, light my fire. int* p = static_cast<int*> (42);
template <class T1, class T2> struct pair;
with one space separating the keyword template
from the list of
formal parameters. For explicit specializations you MAY (and are
RECOMMENDED to) write template<>
:
template<> struct pair<int, int> { ... };
()
operator is not a list of arguments.
class Foo { public: Foo (); virtual ~Foo (); bool operator() (int n); };
void
if your function or method does not take any
argument. The C++ way of doing is to simply write that your function does not
take any argument.
Don't do this:
int main(void) { return 0; }
Write this instead (without the comments, obviously):
int main () // Not like C: main can't be passed any argument { } // In C++, main implicitly returns 0
int foo (int n) { return bar (n); }
Don't put initializations or constructor invocations on the same line
as the constructor. As a matter of fact, you MUST NOT even leave
the colon on that line. Instead of A::A (): B (), C()
, write
either:
A::A () : B (), C () { }
or
A::A () : B (), C () { }
Rationale: the initialization belongs more to the body of the constructor than its signature. And when dealing with exceptions leaving the colon above would yield a result even worse than the following.
A::A () try : B (), C () { } catch (...) { }