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

c++

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

my (yuiwong.org) c++ basics 01

#


tips

封装

  • 要像个对象, 不是有个 class 关键字就可以了
  • 视需要 少用 static

继承

  • 多用于实现接口
  • 可以用 组合 就不用继承

多态

  • root class, virtual dtor !!
  • 设计模式时多用

namespace

  • namespace required!
  • usually NO using
  • 可以简化相同前缀 / 前缀一样可以省略
  • 最好不要在名字前加前缀或缩写前缀 先考虑使用名字空间
  • enum 可以考虑: 名字空间 + Type

重载和默认参数

  • 重载最好只看参数个数, 默认参数时更要注意, 然后最好取和更合适的名字
e.x. c++ NULL is 0

设计模式

  • 视需要, 能用就用

模块复用和统一维护

  • 提取公共部分 先考虑封装成通用类和接口
  • 再者考虑封装成库和 git submodule

访问控制

  • 先考虑 private 和 friend class

引用

  • 参数: 第一个考虑可不可以使用 常引用

智能指针

  • 例如内存使用较大 先考虑使用堆并且使用智能指针自动回收
  • 注意 std::auto_ptrstd::unique_ptr (支持或不支持 C++11)

迭代器

  • erase all by iterator.

ref. TODO

e.x.
/* erase all (use iterator) */
#define ERASEALL(__0s, __0ittp, __0k, __0c) do { \
    __0ittp it = (__0s).begin(); \
    size_t fastforw = 0; \
    while (it != (__0s).end()) { \
        if ((__0k) == *(it)) { \
            ++(__0c); \
            (__0s).erase(it); \
            it = (__0s).begin() + fastforw; \
        } else { \
            ++fastforw; \
            ++it; \
        } \
    } \
} while(0)

stl

  • 非线程安全 => 可以再封装一下使可重入

const

  • 不修改就加 const, 并且考虑使用 { } 以立即释放
  • 也包括值类型作为参数 这样实现的函数内部就避免改错
  • cv: 尽量限制方法 const
  • 通常返回值不要加 const (包括返回对象)
  • 如有需要 使用 static_const 去掉 const 例如 const 方法内需要访问 mutex

cast

  • 使用 C++ 的 cast
static_cast
reinterpret_cast
const_cast
dynamic_cast

线程安全

  • 必须注意 头次实现就支持
  • 先考虑使用 scoped_lock 不支持 C++11 see TODO
  • 注意线程内使用回调时要避免可能出现的死锁

struct

  • 视需要 尽量使用构造函数以及重载操作符 初始化等使用

返回值

  • 最好不要返回 bool

assert

  • 测试 单元测试时必须要用

throw try catch

  • 返回引用考虑 throw
  • 测试 单元测试时必须要用

comments

  • 一定要有
  • 尽量不使用 // (太懒太难看)

inline

  • 最好不使用

see also

git submodule

git submodule

build-linux.sh
#!/bin/sh

set -x
git pull
if [ $? -ne 0 ]; then echo "FAIL!!"; exit 1; fi
git submodule init
if [ $? -ne 0 ]; then echo "FAIL!!"; exit 1; fi
git submodule update
if [ $? -ne 0 ]; then echo "FAIL!!"; exit 1; fi
make OYW_HASQT=1 OYW_CCC=1 clean
if [ $? -ne 0 ]; then echo "FAIL!!"; exit 1; fi
make OYW_HASQT=1 OYW_CCC=1
if [ $? -ne 0 ]; then echo "FAIL!!"; exit 1; fi
echo "Done"
  • Below are examples

add submodule

...
$ git submodule add https://github.com/iamyuiwong/cppnetwork.git modules/cppnetwork
...

$ cat .gitmodules
[submodule "modules/base64ende"]
    path = modules/base64ende
    url = https://github.com/iamyuiwong/base64ende.git
[submodule "modules/checksum"]
    path = modules/checksum
    url = https://github.com/iamyuiwong/checksum.git
[submodule "modules/cppnetwork"]
    path = modules/cppnetwork
    url = https://github.com/iamyuiwong/cppnetwork.git

add submodule url (from .gitmodules) to .git/config 以及后续 submodules clone

Set url(s):
git submodule init
Clone:
git submodule update

brand-new clone master and sub modules:

git clone --recursive https://github.com/iamyuiwong/liboywcppbase.git

watch

git submodule
Or.
git submodule status
Or.
git submodule status --recursive

E.x.
 38837fa4806b58bc17a002c5a1db36b95b1be7e5 modules/base64ende (heads/master)
 fdbf9709c66cb027e44b92cf12b9f3f5e893083e modules/checksum (heads/master)
 cc1977851ebbf2c72d60d88d49161be43e5f3796 modules/cppnetwork (heads/master)

get remote latest need by master

E.x.
git submodule update --remote

Or.
git submodule update --remote modules/cppnetwork

foreach

E.x.
git submodule foreach 'git checkout master'

git submodule foreach 'git pull'

update master deps.

  • 1 git submodule foreach 'git pull'
  • 2 add and commit