C++代码撰写风格(GNU)

sevencat 2004-03-25 09:31:56
C++ Standard Library Style Guidelines DRAFT 2001-01-15
-------------------------------------

This library is written to appropriate C++ coding standards. As such,
it is intended to precede the recommendations of the GNU Coding
Standard, which can be referenced here:

http://www.gnu.org/prep/standards_toc.html

ChangeLog entries for member functions should use the
classname::member function name syntax as follows:

1999-04-15 Dennis Ritchie <dr@att.com>

* src/basic_file.cc (__basic_file::open): Fix thinko in
_G_HAVE_IO_FILE_OPEN bits.

Notable areas of divergence from what may be previous local practice
(particularly for GNU C) include:

01. Pointers and references
char* p = "flop";
char& c = *p;
-NOT-
char *p = "flop"; // wrong
char &c = *p; // wrong

Reason: In C++, definitions are mixed with executable code. Here,
p is being initialized, not *p. This is near-universal
practice among C++ programmers; it is normal for C hackers
to switch spontaneously as they gain experience.

02. Operator names and parentheses
operator==(type)
-NOT-
operator == (type) // wrong

Reason: The == is part of the function name. Separating
it makes the declaration look like an expression.

03. Function names and parentheses
void mangle()
-NOT-
void mangle () // wrong

Reason: no space before parentheses (except after a control-flow
keyword) is near-universal practice for C++. It identifies the
parentheses as the function-call operator or declarator, as
opposed to an expression or other overloaded use of parentheses.

04. Template function indentation
template<typename T>
void
template_function(args)
{ }
-NOT-
template<class T>
void template_function(args) {};

Reason: In class definitions, without indentation whitespace is
needed both above and below the declaration to distinguish
it visually from other members. (Also, re: "typename"
rather than "class".) T often could be int, which is
not a class. ("class", here, is an anachronism.)

05. Template class indentation
template<typename _CharT, typename _Traits>
class basic_ios : public ios_base
{
public:
// Types:
};
-NOT-
template<class _CharT, class _Traits>
class basic_ios : public ios_base
{
public:
// Types:
};
-NOT-
template<class _CharT, class _Traits>
class basic_ios : public ios_base
{
public:
// Types:
};

06. Enumerators
enum
{
space = _ISspace,
print = _ISprint,
cntrl = _IScntrl
};
-NOT-
enum { space = _ISspace, print = _ISprint, cntrl = _IScntrl };

07. Member initialization lists
All one line, separate from class name.

gribble::gribble()
: _M_private_data(0), _M_more_stuff(0), _M_helper(0);
{ }
-NOT-
gribble::gribble() : _M_private_data(0), _M_more_stuff(0), _M_helper(0);
{ }

08. Try/Catch blocks
try
{
//
}
catch (...)
{
//
}
-NOT-
try {
//
} catch(...) {
//
}

09. Member functions declarations and definitions
Keywords such as extern, static, export, explicit, inline, etc
go on the line above the function name. Thus

virtual int
foo()
-NOT-
virtual int foo()

Reason: GNU coding conventions dictate return types for functions
are on a separate line than the function name and parameter list
for definitions. For C++, where we have member functions that can
be either inline definitions or declarations, keeping to this
standard allows all member function names for a given class to be
aligned to the same margin, increasing readibility.


10. Invocation of member functions with "this->"
For non-uglified names, use this->name to call the function.

this->sync()
-NOT-
sync()

Reason: Koenig lookup.

11. Namespaces
namespace std
{
blah blah blah;
} // namespace std

-NOT-

namespace std {
blah blah blah;
} // namespace std

12. Spacing under protected and private in class declarations:
space above, none below
ie

public:
int foo;

-NOT-
public:

int foo;

13. Spacing WRT return statements.
no extra spacing before returns, no parenthesis
ie

}
return __ret;

-NOT-
}

return __ret;

-NOT-

}
return (__ret);


14. Location of global variables.
All global variables of class type, whether in the "user visable"
space (e.g., cin) or the implementation namespace, must be defined
as a character array with the appropriate alignment and then later
re-initialized to the correct value.

This is due to startup issues on certain platforms, such as AIX.
For more explanation and examples, see src/globals.cc. All such
variables should be contained in that file, for simplicity.

15. Exception abstractions
Use the exception abstractions found in functexcept.h, which allow
C++ programmers to use this library with -fno-exceptions. (Even if
that is rarely advisable, it's a necessary evil for backwards
compatibility.)

16. Exception error messages
All start with the name of the function where the exception is
thrown, and then (optional) descriptive text is added. Example:

__throw_logic_error(__N("basic_string::_S_construct NULL not valid"));

Reason: The verbose terminate handler prints out exception::what(),
as well as the typeinfo for the thrown exception. As this is the
default terminate handler, by putting location info into the
exception string, a very useful error message is printed out for
uncaught exceptions. So useful, in fact, that non-programmers can
give useful error messages, and programmers can intelligently
speculate what went wrong without even using a debugger.

The library currently has a mixture of GNU-C and modern C++ coding
styles. The GNU C usages will be combed out gradually.

Name patterns:

For nonstandard names appearing in Standard headers, we are constrained
to use names that begin with underscores. This is called "uglification".
The convention is:

Local and argument names: __[a-z].*

Examples: __count __ix __s1

Type names and template formal-argument names: _[A-Z][^_].*

Examples: _Helper _CharT _N

Member data and function names: _M_.*

Examples: _M_num_elements _M_initialize ()

Static data members, constants, and enumerations: _S_.*

Examples: _S_max_elements _S_default_value

...全文
206 9 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
RookieStar 2004-03-25
  • 打赏
  • 举报
回复
内容好多,看得头晕又记不住!
adamsun 2004-03-25
  • 打赏
  • 举报
回复
ft,灌水吗?

:-)
fireinsky 2004-03-25
  • 打赏
  • 举报
回复
贴这么多干吗?这又不是看书的地方.
sevencat 2004-03-25
  • 打赏
  • 举报
回复
1格式化代码工具:GNU的indent,sourceforge上的astyle都可以
简单的风格:
这个是ANSI的风格:
namespace foospace
{
int Foo()
{
if (isBar)
{
bar();
return 1;
}
else
return 0;
}
}


K&R风格

namespace foospace {
int Foo() {
if (isBar) {
bar();
return 1;
} else
return 0;
}
}

LINUX风格
namespace foospace
{
int Foo()
{
if (isBar) {
bar();
return 1;
} else
return 0;
}
}


GNU风格
namespace foospace
{
int Foo()
{
if (isBar)
{
bar();
return 1;
}
else
return 0;
}
}

JAVA风格
class foospace {
int Foo() {
if (isBar) {
bar();
return 1;
} else
return 0;
}
}

老式的函数声明:
char *
create_world (x, y, scale)
int x;
int y;
float scale;
{
. . .
}




2 呵,加下划线的一般表示是内部使用的。还有些人喜欢在后面加下划线,也是类的内部使用的。

sevencat 2004-03-25
  • 打赏
  • 举报
回复
刚才还没贴完呢。
Don't use names in the same scope that differ only in the prefix,
e.g. _S_top and _M_top. See BADNAMES for a list of forbidden names.
(The most tempting of these seem to be and "_T" and "__sz".)

Names must never have "__" internally; it would confuse name
unmanglers on some targets. Also, never use "__[0-9]", same reason.

--------------------------

[BY EXAMPLE]

#ifndef _HEADER_
#define _HEADER_ 1

namespace std
{
class gribble
{
public:
// ctor, op=, dtor
gribble() throw();

gribble(const gribble&);

explicit
gribble(int __howmany);

gribble&
operator=(const gribble&);

virtual
~gribble() throw ();

// argument
inline void
public_member(const char* __arg) const;

// in-class function definitions should be restricted to one-liners.
int
one_line() { return 0 }

int
two_lines(const char* arg)
{ return strchr(arg, 'a'); }

inline int
three_lines(); // inline, but defined below.

// note indentation
template<typename _Formal_argument>
void
public_template() const throw();

template<typename _Iterator>
void
other_template();

private:
class _Helper;

int _M_private_data;
int _M_more_stuff;
_Helper* _M_helper;
int _M_private_function();

enum _Enum
{
_S_one,
_S_two
};

static void
_S_initialize_library();
};

// More-or-less-standard language features described by lack, not presence:
# ifndef _G_NO_LONGLONG
extern long long _G_global_with_a_good_long_name; // avoid globals!
# endif

// Avoid in-class inline definitions, define separately;
// likewise for member class definitions:
inline int
gribble::public_member() const
{ int __local = 0; return __local; }

class gribble::_Helper
{
int _M_stuff;

friend class gribble;
};
}

// Names beginning with "__": only for arguments and
// local variables; never use "__" in a type name, or
// within any name; never use "__[0-9]".

#endif /* _HEADER_ */


namespace std
{
template<typename T> // notice: "typename", not "class", no space
long_return_value_type<with_many, args>
function_name(char* pointer, // "char *pointer" is wrong.
char* argument,
const Reference& ref)
{
// int a_local; /* wrong; see below. */
if (test)
{
nested code
}

int a_local = 0; // declare variable at first use.

// char a, b, *p; /* wrong */
char a = 'a';
char b = a + 1;
char* c = "abc"; // each variable goes on its own line, always.

// except maybe here...
for (unsigned i = 0, mask = 1; mask; ++i, mask <<= 1) {
// ...
}
}

gribble::gribble()
: _M_private_data(0), _M_more_stuff(0), _M_helper(0);
{ }

inline int
gribble::three_lines()
{
// doesn't fit in one line.
}
} // namespace std


darksmile 2004-03-25
  • 打赏
  • 举报
回复
基本没什么问题
说几点自己的看法:
1 什么时候该空行,什么时候该断行,什么时候要留空格,缩进几个空格属于书写风格,没必要强行规定。但是在多人协作时应尽量保持统一,现在的很多代码格式化工具都可以很好的自动实现格式化。
2 最好不要在标识符前加下划线,搞不好会有麻烦的
3 给变量加m,s之类的前缀虽然看起来很好,但是实际上毫无意义,真的很傻,不推荐使用。
这样做唯一的作用在于给阅读代码的人以整齐划一的感觉,对理解代码的含义没有好处。
试比较:
啊啊啊啊
啊啊啊啊
啊啊啊啊
啊啊啊啊

莎士比亚的十四行诗,哪一个更整齐,你又更愿意读哪一个?
yonyon 2004-03-25
  • 打赏
  • 举报
回复
up
sevencat 2004-03-25
  • 打赏
  • 举报
回复
哦,这里面没有强制性的东东,只有一些建议。

还有些是经验之谈。
Jinhao 2004-03-25
  • 打赏
  • 举报
回复
既然都说是风格问题,那怎么好看怎么写,为什么非要强加呢?而指明另一种风格是错误的呢?你喜欢靠左,我喜欢靠右走,又不是开车,为什么不允许我靠右走呢?

15,447

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 非技术区
社区管理员
  • 非技术区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧