how to cpp (coding)

how to cpp (coding)

my cpp standard (style / specification / .. how to coding!)

#


list

simple thing should be simple

  • no redundant prefix, e.x. m / _ / i / ..
  • no redundant suffix, e.x. _ / ..
  • example not:
bool bShouldReboot;
int iNumber;
AAAA maaaa;
BBBB bbbb_;


/* then access example */
if (bShouldReboot) { /* where the bShouldReboot from */
}
bbbb_.foo(); /* where the bbbb_ from */

but should be:

bool shouldReboot;
int number;
AAAA aaaa;
BBBB bbbb;

/* then access example */
if (self.shouldReboot) { /* the shouldReboot is myself */
}

if (this->shouldReboot) {
}

this->bbbb.foo(); /* the bbbb from this object */

about ostream

  • better not use endl .. std::endl, but \n is ok !

indent

  • usually 1 is enough!!

example not

void somemaybeokfooMaybebadaaa(const AAAA& aaaa, const BBBB& bbbb,
                               const CCCC& cccc, const DDDD& dddd,
                               const EEEE& eeee);

but should be

void somemaybeokfooMaybebadaaa(
    const AAAA& aaaa,
    const BBBB& bbbb,
    const CCCC& cccc,
    const DDDD& dddd,
    const EEEE& eeee);

80

  • yes !! usually max width of each line is 80
  • 可以换行啊 !!!

no garbage

  • no garbage lines at middle of file
  • no garbage lines at end of file
  • no garbage space (space / table / ..) at end of line
  • no garbage space (space / table / ..) at begin of line(
    example, need 2 but 3 provided)

1 space

  • example not:
if(some){
}

sum=a+b;

but shoule be

if (some) {
}

sum = a + b;

block statement

  • always {}, even if 1 statement, example:
/* NOT */
some;
if (ok)
    fly();
else
    walk();
other;

/* BUT SHOULE BE: */
some;
if (ok) {
    fly();
} else {
    walk();
}
other;

/* and further more is good: */
some;
if (ok) {
    fly();
    saysomething();
} else {
    walk();
}
stopFirst();
other;

path

  • example for include: NOT ../../.hpp or ../.hpp
    or too/many/name/...hpp

but should be: some/…hpp and use -I...

lower and upper

  • type: Type
  • instance / member: instance / data / foo / staticFoo
  • generic function: Foo

prefix

  • better no! if could be simple !!
  • global: use k e.x. kGraphProcessor.
    (NOT use e.x. g)

plusplus

  • if not have to be some++(case for some++ when which can simplify 2 to 1)

SO USUALLY use ++some (not use some++ if not have to), because:
i see plus one, the result of the expression should be plused one !!
but this expression maybe little silly!

  • example, better:
for (size_t i = 0; i < sz; ++i) {
}

/* got whatsthis */
++whatsthis;/* should plus one or whatsthis += 1; */
someFoo(whatsthis);

when to declare

when to declare: when use, example

/* BAD: heyheyhey example */
Some heyheyhey;/* BAD */
doSome();
doOther();
thisFooNeedRefAndAlwaysSetIt(heyheyhey);

/* BAD: heyheyhey example 2 */
Some heyheyhey = 0;/* BAD */
...
thisFooNeedRefAndMaybeNotSetIt(heyheyhey);

/* BAD: heyheyhey example 3 */
Some heyheyhey;/* BAD */
heyheyhey = 0;/* BAD */
...
thisFooNeedRefAndMaybeNotSetIt(heyheyhey);

/* BAD: heyheyhey example 4 */
Some heyheyhey;/* BAD */
doSome();
...
heyheyhey = 0;/* BAD */
thisFooNeedRefAndMaybeNotSetIt(heyheyhey);

/* GOOD: heyheyhey example */
doSome();
doOther();
Some heyheyhey;/* GOOD ! */
thisFooNeedRefAndAlwaysSetIt(heyheyhey);

/* GOOD: heyheyhey example 2 */
doSome();
...
Some heyheyhey = 0;/* GOOD ! */
thisFooNeedRefAndMaybeNotSetIt(heyheyhey);

how to assign init

how to assign: do not assign repeatedly or maybe repeatedly, example

/* bad: */
size_t count = 10;
if (ok) {
    count  = 100;
}

/* good: */
size_t count;
if (ok) {
    count  = 100;
} else {
    count  = 10;
}

should dump when need

  • for data thread safe
  • for less call: if use not only once => dump it!, example
/*
 * consider now datas is latched .. here means
 * bad case:
 */
some();
for (size_t i = 0; i < datas.size(); ++i) {
    foo(datas[i]);
}
other();

/*
 * bad case 2:
 */
sayToSomebody(getNameById(1), "hi");
sayToSomebody(getNameById(1), "hey");

/*
 * consider now datas is latched .. here means
 * good case:
 */
some();
{
    const size_t sz = datas.size();/* dump the size */
    for (size_t i = 0; i < sz; ++i) {
        foo(datas[i]);
    }
}
other();

/*
 * good case 2:
 */
{
    const std::string who = getNameById(1);/* dump the name */
    sayToSomebody(who, "hi");
    sayToSomebody(who, "hey");
}

how to debug by output log

  • __FILE__
  • __LINE__
/* SO BAD example */
some();
std::cout << "aaaaa" << std::endl;
watch();
std::cout << "bbbbb222222!!!" << std::endl;/* what u b !! */

/* GOOD example */
some();
std::cout << "(" << __FILE__ << "+" << __LINE__ << ")" NAME " "
    << "before watch\n";/* good */
watch();
std::cout << "(" << __FILE__ << "+" << __LINE__ << ")" NAME " "
    << "after watch\n";/* good */

/* further more */
const int err = fly();
if (err) {
    std::cerr << "(" << __FILE__ << "+" << __LINE__ << ")" NAME " "
        << "ERROR: fly fail: " << err << "\n";/* so good */
    die();
}

no flag

  • just better NOT use the name flag, example:
/* bad case */
void setStartable(bool flag)
{
    this->startable = flag;
}

/* bad case 2 */
void setResult(bool flag)
{
    this->startable = flag;
}

/* good case: just to what it should be */
void setStartable(bool startable)
{
    this->startable = startable;
}

/* good case 2 */
void setResult(bool result)
{
    this->result = result;
}

further

c++

my c++ .. yuiwong.org .. c++

#


tips

c++ !!!

  • 封装
  • 继承
  • polymorphism 多态

polymorphism 多态

  • 多态: 是对于不同对象接收相同消息时产生不同的动作.
  • c++ 的多态性具体体现在运行和编译两个方面:
    • 在程序运行时的多态性通过继承和虚函数来体现
    • 在程序编译时多态性体现在函数和运算符的重载
  • c impl. 封装: struct

  • c impl. 继承: container_of

/**
 * @brief YUIWONGORGPOSIX_CONTAINER_OF / YUIWONGORGPOSIX_DOWNCAST (container_of) (c)
 * @description 结构体: 通过成员地址找到首地址 / downcast parent to sub
 * @param
 * - `type':
 *   首地址 - 类型
 *   Or. downcast - "subtype" "子类"类型
 * - `memptr'
 *   首地址 - 成员地址
 *   Or. donwcast - parptr: 子类的"父类"成员(组合)的地址
 * - `mem'
 *   首地址 - mem 成员名
 *   Or. downcast - "父类作为子类的成员"(组合)的名字
 */
#define YUIWONGORGPOSIX_CONTAINER_OF(type, memptr, mem) \
    ((type *)((unsigned long)(memptr) \
    - (unsigned long)&((type *)0)->mem))
#define YUIWONGORGPOSIX_DOWNCAST YUIWONGORGPOSIX_CONTAINER_OF
  • c impl. 多态: 函数指针

sort

  • 冒泡排序
  • 快速排序
  • 选择排序

see TODO

size

misc

  • stl std::map 实现: 红黑树
  • stl std::vector 调整大小
  • iterator / iterator 模式
  • template TODO
  • typename and classname TODO
  • typedef TODO
  • typealias TODO

  • 空值类型: void

  • sometype *restrict someptrrestrict:

所有修改该指针所指向内存中内容的操作都必须通过该指针或者直接来自该指针的值
(例如 pointer + 1)

* gcc clang .. c++: `__restrict__`
* vc++ .. c++: `__restrict` and `__declspec(restrict)`
* c99 `memcpy`:
`void * memcpy(void *restrict dest, const void *restrict src, size_t n);`
`restrict` => let `memcpy()` 可以假定两个内存区域没有重叠.
=> 使用 `memcpy()` 时, 您必须确保没有重叠区域. 这是程序员的任务的一部分.
* see <https://yuiwong.org/gitweball/?p=cpp-basics.git;a=tree>
  • memcpy and memmove
  • __attribute__(GNU), __declspec(ms) and #pragma: 编译器工具到语言的扩展
    • Attributes 属性
      C++11 provides a standardized syntax for compiler/tool extensions
      to the language.
      Such extensions were traditionally specified using #pragma directive
      or vendor-specific keywords (like __attribute__ for GNU
      and __declspec for Microsoft).
    • see https://yuiwong.org/gitweball/?p=cpp-basics.git;a=tree
  • explicit (显式)
    • explicit 是避免构造函数的参数自动转换为类对象的标识符
      => 必须要显示地调用构造函数
      => 即类似看到效果: 避免了创建临时对象
      (实际并没有看到调用两次 ctor 而是避免了自动转换)
    • see https://yuiwong.org/gitweball/?p=cpp-basics.git;a=tree
  • union TODO

  • assign operator: 注意: 需要判断是否是本身 特别不是通过构造函数实现时
  • stream operator TODO
  • cast operator TODO
  • subscript 即 [] operator

    • std::map: 没有 idx 下标操作, 有 key 下标操作
    • std::list 无下标操作
    • std::set 无下标操作
  • c++ struct 可以有构造函数、普通函数 访问修饰 继承等 像 class 一样

  • static var 会初始化 (包括作用域内)

c++ advanced

  • 智能指针
    • see TODO
  • 设计模式

    • see TODO
  • 虚函数 虚函数表 虚函数表地址 and 运行时多态 TODO

  • 虚析构函数 TODO
  • 子类析构父类析构 TODO
  • container TODO
  • collection TODO

  • stl c++11 and above multi-threading

    • <atomic> atomic (header)
    • <thread> thread (header)
    • <mutex> mutex (header)
    • <condition_variable> condition variable (header)
    • <future> future (header)
    • see TODO
  • optional, nullopt_t, nullopt TODO

  • nullptr_t, nullptr TODO
  • any TODO
  • var.. TODO
  • forward TODO

  • typeid (header <typeinfo>) 用于类型检查 => rtti

    • example
    const std::type_info& ti1 = typeid(A);
    const std::type_info& ti2 = typeid(A);
    assert(&ti1 == &ti2); /* not guaranteed */
    assert(ti1.hash_code() == ti2.hash_code()); /* guaranteed */
    assert(std::type_index(ti1) == std::type_index(ti2)); /* guaranteed */
    
    • see TODO
  • cast
    • 隐式转换
    • 显式转换
    • const_cast
    • static_cast
    • reinterpret_cast
    • dynamic_cast
    • cast_operator 转换操作符 (e.x. std::nullptr)
  • some more casts
    • downcast: downcast parent to sub(child)
    • upcast: upcast sub(child) to parent
    • sidecase: cast to 兄弟类
    • see TODO

see also