不包含不用的头文件;
尽可能使用前向声明替代头文件包含;
将嵌套类实现放在实现代码中;
将静态实现细节尽可能放在实现代码中;
不要在头文件生命中inline代码;
不要inline构造析构函数;
不要inline虚函数;
原文如下,链接是:http://www.chromium.org/developers/coding-style/cpp-dos-and-donts
Minimize Code in Headers
Don't include headers you don't need. Especially in headers.
I've seen several places where a header will include something, like <deque> or "googleurl/src/gurl.h" and then not use the std::deque or GURL in the file. These are probably oversights from previous refactorings or reorganizations where the files used to be necessary, but they should be fixed whenever they are seen.Forward declare classes instead of including headers.
You can use forward declarations in all the following cases:class Forward;
class ObjectUser {
public:
ObjectUser(Forward by_value);
void OrByPointer(Forward* by_pointer);
void OrByReference(const Forward& by_reference);
Forward OrReturnValue();
private:
Forward* pointer_member_;
scoped_ptr<Forward> most_smart_pointer_templates_;
std::vector<Forward> some_stl_containers_;
std::map<std::string, Forward> values_in_maps_;
};
But you can't forward declare in other situations:
class WontCompile {private:// But you can't just:Forward cant_full_member_;std::deque<Forward> cant_some_other_stl_ containers_;};
Whenever you can forward declare, you should forward declare instead of including a header.
Move inner classes into the implementation.
You can also forward declare classes inside a class:class Whatever {
public:
/* ... */
private:
struct DataStruct;
std::vector<DataStruct> data_;
};
Any headers that DataStruct needed no longer need to be included in the header file and only need to be included in the implementation. This will often let you pull headers includes out of the header. For reference, the syntax in the implementation file is:
struct Whatever::DataStruct {
};
Note that sometimes you can't do this because a handful of STL data structures require the full definition at declaration time (most notably, std::deque and the STL adapters that wrap it).
Move static implementation details to the implementation whenever possible.
If you have the class in a header file:#include "BigImplementationDetail.h"
class PublicInterface {
public:
/* ... */
private:
static BigImplementationDetail detail_;
};
You should try to move that from a class member into the anonymous namespace in the implementation file:
namespace {
BigImplementationDetail detail_;
} // namespace
That way, people who don't use your interface don't need to know about or care about BigImplementationDetail.
You can do this for helper functions that have hard to forward declare types, too.
Stop inlining code
BACKGROUND: We're doing too much inlining. Remember that definitions in classes are requested to be inlined. Remember that asking the compiler to inline a method is a suggestion, one that's often ignored by the compiler. A compiler that never inlined anything would be perfectly standards compliant. Every file that has to use an inline method will also emit a function version in the resulting .o, even if the method was inlined. (This is to support function pointer behaviour properly.)class InlinedMethods {
InlinedMethods() {
// This constructor is equivalent to having the inline keyword in front
// of it!
}
void Method() {
// Same here!
}
};
class DontDoThis {public:int ComputerSomehting() {int sum =0;for (int i = 0; i < shurg; ++i) {sum += OtherMethod(i, ... );}return sum;}};
Anything more than a few operations on integral data types will probably not be inlined by the compiler. Remember that inline is a suggestion, and that you're just adding crud to the .o files which the linker will need to do work to resolve.
If the method deals with implementation details, there's also a good chance that you could eliminate some included headers in the header.
Stop inlining constructors and destructors.
Constructors and destructors are often significantly more complex than you think they are, especially if your class has any non-POD data members. Many STL classes have inlined constructors/destructors which may be copied into your function body. Because the bodies of these appear to be empty, they often seem like trivial functions that can safely be inlined. Don't give in to this temptation. Define them in the implementation file unless you really need them to be inlined. Even if they do nothing now, someone could later add something seemingly-trivial to the class and make your hundreds of inlined destructors much more complex.For more information, read Item 30 in Effective C++.
Even worse though, inlining constructors/destructors prevents you from using
forward declared variables.
class Forward;
class WontCompile {
public:
// THIS WON'T COMPILE, BUT IT WOULD HAVE IF WE PUT THESE IN THE
// IMPLEMENTATION FILE!
//
// The compiler needs the definition of Forward to call the
// vector/scoped_ptr ctors/dtors.
Example() { }
~Example() { }
private:
std::vector<Forward> examples_;
scoped_ptr<Forward> super_example_;
};
When you CAN inline constructors and destructors.
The above case had two class members and that's a large part of the reason it's more complex than it seems. There are cases where it is better to have an inline constructor and
no destructor.
struct Data {Data() : count_one(0), count_two(0) {}
int count_one;int count_two;};
If you aren't sure, than you probably shouldn't try this.
You CAN inline virtual destructors in pure abstract base classes.
For example, you don't have to make a CC file for this:
class Interface {public:virtual ~Interface() {}virtual void DoSomething(int parameter) = 0;virtual int GetAValue() = 0;};
class ClaimsToBeAnInterface : public base:RefCounted<ClaimsToBeAnInterface> {public:virtual ~ClaimsToBeAnInterface() { /* But derives from a template! */ }};
class HasARealMember {public:virtual void InterfaceMethod() = 0;virtual ~HasARealMember() {}
protected:
vector<string> some_data_;};
class Foo {public:
int count() const { return count_; }
private:
int count_;};
struct MyData {vector<GURL> urls_;base::Time last_access_;};
class Manager {public:MyData get_data() { return my_data_; }
private:MyData my_data_;};