C++进阶笔记

C++进阶笔记

C++:

  • C++语言
  • C++标准库

推荐书籍:
《Effective C++》
《C++ primer》
《STL源码剖析》

C:

Type(built-in,struct)
data
Function

C++ 面向对象

数据和函数包在一起,数据有很多分,函数只有一份。以此创建对象。

class,struct

例子1,复数

complex c1(2,1);

complex c2;

complex *pc = new complex(0,1)

例子2:

string s1("hello ");

string s2("World ");

string *ps = new string;

C++程序代码的基本形式

  • 头文件(声明)(防卫式)
  • 主程序
  • 标准库

大方向:

  • 把构造函数放在 private区,是存在的
  • 参数传递最好传引用(to const)
  • 返回值传递最好传引用(to const)
  • 相同class的各个object互为friend友元
  • 什么时候不可以return by reference?
    • 返回的是新创建的东西,返回的是local的东西。
  • 传递者需要知道是以reference形式接收
  • 全局函数没有this指针
  • temp object 临时对象 typename()
  • 创建新的local对象,直接返回类的名称+括号来new一个对象。
  • 在设计类的时候,要考虑一下方法要放在成员function还是local Function

C++三大函数(three Big):

  • 拷贝构造函数
  • 拷贝复制
  • 析构函数

如果一个类有指针成员,就必须有拷贝构造和拷贝复制函数

##栈,堆与内存管理:
scope:作用域
{}

Stack:是存在于某个作用域(scope)的一块内存空间(memory space)。例如当你调用函数,函数本身即会形成一个satck,用来放置它接收的参数,以及返回地址。在函数本身内声明的任何变量,起所使用的内存块都取自与stack。
stack object只要离开作用域,它的生命周期就终止了

Heap:或者说是system Heap,是由操作系统提供的一块全局(global)内存空间,程序可动态分配(dynamic allocated,就是用new),从中取得若干块(block)

生命周期:

  • local object 又叫做auto object ,因为它会被自动清理,它的析构函数会被自动调用。
  • static local object 的生命周期。static object,其生命在作用域(scope)结束后仍然存在。知道整个程序结束。
  • glabal object 的生命周期任何{}之外。其生命周期在整个程序结束后才结束。
  • heap object的生命周期

内存泄露,内存溢出

  • 内存泄露:拥有者本来有一块内存,经过某些事件或者某些作用域之后,拥有者对这块内存失去了控制,以至于拥有者没有办法还给操作系统。(内存是一个很重要的资源)

  • new:先分配一块memory,再调用构造函数ctor,new被分解为三个动作(Complex * pc = new Complex(1,2)):

    • 分配内存memory ( void* mem = operator new(sizeof(object))),内部调用malloc。
    • 转型(pc = static_cast(men))
    • 构造函数(pc->Complex:complex(1,2)),注意,构造函数的全名是 Complex::Complex(pc,1,2),其中pc也就是this指针
  • array new 一定要搭配 array delete

  • delete:先调用析构函数dtor,再释放内存。

    • 析构函数
    • 释放内存
  • 例如:delete ps;

    • String::~String(ps);//析构函数
    • operator delete(ps);//释放内存(调用free(ps))
  • 内存溢出:

##动态分配所得的内存块(memory block),in VC

  • 调试模式(debug)下和发布模式(release)下的动态分配内存是不一样的

动态分配所得的array

Complex* p = new Complex[3]
String* s = new String[3]

##!!注意一种情况,连串赋值的时候,返回类型不能为void!要返回对象(或者的引用)
return &this;//传出去的人,不必知道接受端用什么形式来接受。this所指的是一个东西,不管是东西还是引用,反正都传东西出去,具体传出去是什么,主要看返回类型。

##namespace 经验谈
namespace起着包装作用

namespace std
{
...
}

使用namespace方法:

  • using directive(指令),例如,using namespace std;这种最方便。
  • using declaration(声明),例如,using std::cout;

##进一步了解static:

complex c1,c2,c3;
cout << c1.real();
cout << c2.real();

原来的形式为

complex c1,c2,c3;
cout << complex::real(&c1);
cout << complex::real(&c2);

此时,c1的地址成为指针。

  • 一份函数,要处理很多个对象。成员函数有一个隐藏的this pointer指针,这个编译器会自动帮我们表现出来。
  • 加了static之后,不属于任何一个对象。
  • 静态函数没有this pointer
  • 静态数据一定要在class外面定义该数据。(定义difination:变量获得内存)
  • 调用static函数的方法有二:
    • 通过object来调用
    • 通过class name来调用

类模板,模板函数

  • 类模板:template
  • 模板函数:template

OOP(Object Oriented Programming),OOD(Object Oriented Design),类与类之间的关系。

  • Inheritance(继承)
    • 表示is-a,表示“是一种!”
    • 构造是由内而外
    • 析构由外而内
    • 父类的析构dtor函数必须是virtual,否则会出现 undefined behavior,也就是说,如果一个类有可能成为父类,那么,它的析构函数一定要是virtual函数。
    • 函数继承的是调用权
  • Composition(复合)
    • 表示 has-a,类里面含有类
    • 构造是由内而外
    • 析构由外而内
  • Delegation(委托):Composition by reference
    • pimpl(Handle / Body)
    • reference counting

Adapter(变压器,改造,适配)

关于virtual函数

  • non-virtual 函数:你不希望派生类derived class 重新定义(override,覆盖)它
  • virtual函数:你希望derived class 重新定义(override,覆盖)它,且你对他已有默认定义
  • pure virtual函数:你希望derived class一定要重新定义(override 覆盖)它,你对它没有默认定义。

例如:

virtual void draw() const = 0; //pure virtual,子类一定要定义
virtual void error(const std::string& msg);//impure virtual
int objectID const; //non-virtual,不需要子类重新定义它

关于泛型编程GP(Generic Programming)和面向对象编程OOP(Object Oriented Programming)

  • 所谓泛型编程,就是使用template(模板)为主要工具用来编写程序,C++中STL正是泛型编程(GP)最成功的作品。
  • 其中,C++基本语法(包括正确使用模板,templates)
  • 学习目标:
    • 使用C++标准库
    • 认识C++标准库(胸中自有丘壑)
    • 良好使用C++标准库
    • 扩充C++标准库

关于C++标准库(C++ Standard Library)和C++标准模板库STL(Standard Template Library)

  • 标准库 大于 STL

  • 标准库以header files形式出现。

    • C++标准库的header files 不带副档名(.h),例如 #include
    • 新式 C header file 不带副档名(.h),例如 #include
    • 旧式 C header file 带有副档名(.h),例如 #include
    • 新式 headers 内的组件封装 namespace “std”
      • using namespace std; or
      • using std::cout;(for example)
    • 旧式的 headers 内的组件不封装 namespace “std”
  • 注意:容器里面的东西一定要一样的大小!

设计模式(经典)

  • Delegation(委托)+ Inheritance(继承)
    • Composite(组合物,合金)
    • Prototype:需要创建一个未来会创建的类,解法:子类自己去创造自己,提交到父类里面。

##关于转换函数,没有返回对象。

non-explicit-one-argument ctor

//转换函数-->没有返回类型
class Fraction
{
public:
    Fraction(int num, int den = 1):m_numerator(num),m_denominatir(den){}

//    operator double() const
//    {
//        return double(m_numerator / m_denominatir);
//    }
    Fraction operator+ (const Fraction& f)
    {
        return Fraction(...);
    }
private:
    int m_numerator;
    int m_denominatir;
};

Fraction f(3,5);
Fraction d = f + 4;//调用 non-explicit ctor 将4 转换为Fraction,然后调用operator +

explicit-one-argument ctor

//转换函数-->没有返回类型
class Fraction
{
public:
    explicit Fraction(int num, int den = 1):m_numerator(num),m_denominatir(den){}

//    operator double() const
//    {
//        return double(m_numerator / m_denominatir);
//    }
    Fraction operator+ (const Fraction& f)
    {
        return Fraction(...);
    }
private:
    int m_numerator;
    int m_denominatir;
};

Fraction f(3,5);
Fraction d = f + 4;//调用 non-explicit ctor 将4 转换为Fraction,饭后调用operator +
  • explicit:外在的, 清楚的 一般在构造函数的前面,指定构造函数或转换函数 (C++11 起)为显式,即它不能用于隐式转换和复制初始化
    ##报错信息:
  • ambiguous:歧义,矛盾,二义。

pointer-line class 智能指针(把一个class设计出来像一个pointer,指针允许的操作,这个class中也是允许的)

template

class shared_ptr
{
public:
    T& operator*() const
    {
        return *px;
    }
    T*operator->() const
    {
        return px;
    }
    shared_ptr(T* p):px(p){}
private:
    T* px;
    long * pn;
};

pointer-like classes 开放迭代器(代表容器里面的元素,可以理解为是一个智能指针)

##function-like class 所谓仿函数,也叫函数对象,操作符重载,小括号 (一个class设计出来像一个function)
C++标准库中,仿函数所使用的奇特的base classes.
##Variadic Templates,用递归继承,tuple

##class template类模板,fanction template 模板函数,number template 成员模板

  • 类模板:

      template 
      class A
      {
      public:
      	A(T r = 0, T i = 0):re(r),im(i){}
      private:
      	T re,im;
      }
    
  • 函数模板:

      template 
      inline 
      const T& min(const T& a, const T& b)
      {
      	return b < a ? b: a;
      }
    

函数模板不必指明它的type,因为函数模板一定是去调用,调用的时候会输入参数。

  • 成员模板

模板特化(specialization)

例子:
//泛化
template < class Key >
struct hash {};
//特化
template<>
struct hash
{
size_t operator()(char x) const {return x;}
};
template<>
struct hash
{
size_t operator()(char x) const {return x;}
};
template<>
struct hash
{
size_t operator()(char x) const {return x;}
};

你可能感兴趣的:(C++)