C And C++ Cookie

1 前言

好的,匆忙地学习完ARM之后,立即转战C++学习。真是有意思的安排啊。おもしろい。
那么我们就开始记录吧。原本这个是写于 2013-04-22 的笔记。 由于最近想看一下 node 的源码,所以,这个笔记又被翻出来啦。

2 模版

2.1 函数模版

template <typename T>

template <class T>
void foo(T param)
{
// do something
}

2.2 类模版

template <class T>
class MyClass
{
    MyClass();
    void swap(T &a, T &b);
}
MyClass<T>::MyClass()
{
    // 初始化操作。
}
template <>
type ClassName<class T>::FunctionName (parameters)

3 重载操作符

type operator sign (parameters);
Expression Operator (@) Function member Global function
@a + - * & ! ~ ++ -- A::operator@( ) operator@(A)
a@ ++ -- A::operator@(int) operator@(A, int)
a@b + - * / % ^ & < > = ! <= >= << >> && A::operator@(B) operator@(A, B)
a@b = += -= *= /= %= ^= &= = <<= >>= [ ] A::operator@(B) -
a(b, c…) ( ) A::operator()(B, C…) -
a->b -> A::operator->() -

Reference: http://www.prglab.com/cms/pages/c-tutorial/oo-programming/overloading-operators.php

4 副本构造器(copy construct)

ClassName(const ClassName &cn);

当重载操作符 = ,并不能深度拷贝的时候,需要用一个副本构造器来避免编译器在找不到副本构造器时,自己创建一个“逐位复制”的副本构造器。

Reference: http://www.cnblogs.com/li-peng/p/3776384.html

5 类型高级转化(Advanced Class Type-casting)

5.1 reinterpert_cast

reinterpret_cast 可以将一个指针转换为任意其它类型的指针。它也可以用来将一个指针转换为一个整型,或反之亦然。
这个操作符可以在互不相关的类之间进行指针转换,操作的结果是简单的将一个指针的二进制数据(binary copy)复制到另一个指针。对指针指向的内容不做任何检查或转换。

5.2 static_cast

static_cast 可以执行所有能够隐含执行的类型转换,以及它们的反向操作(即使这种方向操作是不允许隐含执行的)。
用于类的指针,也就是说,它允许将一个引申类的指针转换为其基类类型(这是可以被隐含执行的有效转换),同时也允许进行相反的转换:将一个基类转换为一个引申类类型。

5.3 dynamtic_cast

dynamic_cast 完全被用来进行指针的操作。它可以用来进行任何可以隐含进行的转换操作以及它们被用于多态类情况下的方向操作。 然而与static_cast不同的是, dynamic_cast 会检查后一种情况的操作是否合法,也就是说它会检查类型转换操作是否会返回一个被要求类型的有效的完整的对象。

5.4 const_cast

6 避免内存泄漏

  1. returndelete
  2. new 出来的地址给调用者

7

7.1 动态链接库

7.1.1 编译

在使用GCC编译程序时,只需加上-shared选项即可,这样生成的执行程序即为动态链接库。例如

gcc hello.c -fPIC -o libhello.so

其中 -fPIC 选项的作用是:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的, 所以动态载入时是通过代码拷贝的方式来满足不同的调用,而不能达到真正的代码段共享的目的。

7.1.2 链接

gcc main.c -L. -lhello -o main

7.2 静态库

7.2.1 编译

gcc hello.c -o hello.o  #这里没有使用-shared

7.2.2 归档

ar -r libhello.a hello.o  #这里的ar相当于tar的作用,将多个目标打包。

ar – create and maintain library archives

程序 ar 配合参数 -r 创建一个新库libhello.a,并将命令行中列出的文件打包入其中。这种方法,如果libhello.a已经存在,将会覆盖现在文件,否则将新创建。

7.2.3 链接

gcc main.c -lhello -L. -static -o main

或者

gcc main.c libhello.a -L. -o main

7.3 ldd

ldd - print shared library dependencies

$ ldd a.out
linux-vdso.so.1 =>  (0x00007fff15100000)
/usr/local/snoopy/lib/snoopy.so (0x00007f436e245000)
/opt/aegis/$LIB/aegis_monitor.so => /opt/aegis/lib64/aegis_monitor.so (0x00007f436e042000)
libc.so.6 => /lib64/libc.so.6 (0x00007f436dca0000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f436da9c000)
/lib64/ld-linux-x86-64.so.2 (0x000000303d200000)

Reference:

8 第一课

<2013-04-22 Mon>

#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
    cout << "hi, icecream" << endl;
}

9 第二课

<2013-04-23 Tue>

9.1 内联函数和重载函数inline

C中宏定义注意二义性:

#define max(a, b) (a)>(b)?(a):(b)

inline 类的成员函数,提过效率。 避免C中宏定义的二义性。 使用1~5行的小程序。不要含有复杂的结构控制语句以及递归。 不能使用函数指针

9.2 函数重载

  1. 函数重载与返回值无关。
  2. 有关:类型,顺序,个数
  3. 默认参数: 在参数列表中的某些参数有默认值时,在调用的时候会报错。代码如下:

    int mul(int a, int b){
      return 1;
    }
    
    int mul(int a, int b, int c = 0, int d = 10){
      return 2;
    }
    /* 下面的代码设置默认值是不被允许的,原因是参数入栈时,没有赋值。 */
    int mul(int a=10, int b=10, int c = 0, int d){
      return 2;
    }
    

9.3 多态

9.3.1 静态多态:

10 第三课

<2013-04-25 Thu>

10.1 动态内存分配

10.1.1 堆空间:

C: malloc / calloc / realloc | free

C++: new | delete (两个操作符)

int * p = new int;              /* 在堆上面分配空间sizeof(int) */
int * p = new int();            /* 初始化为0(加上()) */

10.1.2 &: 取地址/引用

int *p = &num;                  /* 取地址符 */
int &p1 = num;                  /* 引用 */

11 第四课

  1. 类的拷贝: 浅拷贝
    深拷贝
  2. 友元类和友元方法

12 第五课

<2013-05-16 Thu>

  1. 虚基类 class A: virtual public b

    不产生二义性 画一个图真难啊

#+BEGIN_DITAA asciiExample.png -o -r -S
+--------------+
|              |
| Hello World! |
|              |
+--------------+
#+END_DITAA

13 写在最后

最后居然还是草草收场,一个没有任何实现的CuteCube!!

Junjia Ni

2013-04-22

2016-11-10 Thu 13:03

Emacs 25.1.1 (Org mode 9.0)

2016-11-10 Thu 12:43