1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 一 C++面向对象高级编程(上) (侯捷)

一 C++面向对象高级编程(上) (侯捷)

时间:2019-02-09 18:38:46

相关推荐

一 C++面向对象高级编程(上) (侯捷)

侯捷 C++八部曲笔记汇总 - - - 持续更新 ! ! !

一、C++ 面向对象高级开发

1、C++面向对象高级编程(上)

2、C++面向对象高级编程(下)

二、STL 标准库和泛型编程

1、分配器、序列式容器

2、关联式容器

3、迭代器、 算法、仿函数

4、适配器、补充

三、C++ 设计模式

四、C++ 新标准

五、C++ 内存管理机制

六、C++ 程序的生前和死后

一、C++面向对象高级编程(上) (侯捷)

C++面向对象高级编程(下) (侯捷)

C++ 正规规范编码

(学C++就是为了效率,要注意小的习惯,一出手就不同凡响!)

1、Header(头文件)中的防卫式声明

complex.h

#ifndef _COMPLEX_#define _COMPLEX_...#endif

2、如果成员函数只读数据(成员变量),而不去修改,则该成员函数后面要加const

const String str("hello C++");str.print();//如果当初设计String::print() 时未指明 const //那么上行便是经由const object 调用 non-const object member function,会出错。

除了上述规则,当成员函数的constnon-const版本同时存在时:

const object只会(只能)调用const版本,non-const object只会(只能)调用non-const版本。

calss template std::basic_string<…>有如下两个 member functions:

charToperator[](size_type pos)const{.../*不必考虑Copy On Write, 常量对象一定不会改内容!*/ }referenceoperator[](size_type pos){.../*必须考虑Copy On Write*/ }

const算函数签名的一部分!

3、参数传递尽量传引用&(速度更快),但是传过去又不想被改,就加const返回类型尽量返回引用&

4、相同class 的各个objects 互为 friends (友元)

class complex{public :complex (double r = 0 , double i = 0): re (r), im (i){}//complex() : re(0), im(0) {} //错误,和第一个冲突了double real ()const {return re; }//不希望改变,函数就加constdouble imag ()const {return im; }int func (const complex& param)//互为 friends {return param.re + param.im;}private:double re, im;} ;{complex c1(2, 1);complex c2;c2.func(c1) ;}

5、以下不能返回引用函数体内创建的对象,离开函数就死亡了!

inline complex operator+ (const complex& x, const complex& y){return complex(real(x) + real(y), imag(x) + imag(y));//类型名 + 小括号 (创建临时对象)}inline complex operator+ (const complex& x, double y){return complex(real(x) + y, imag(x));}inline complex operator + (double x, const complex& y){return complex(x + real(y), imag(y));}

6、如果拷贝带指针,一定不要用编译器默认版本,要自己写!(防止浅拷贝)

class String{public:String(const char* cstr = 0);String(const String& str);String& operator=(const String& str);~String();char* get_c_str() const {return m_data; }private:char* m_data;//指针};inline String::String(const char* cstr = 0){if (cstr) {m_data = new char[strlen(cstr)+1];strcpy(m_data, cstr);} else {// 未指定初值 m_data = new char[1];*m_data = '\0';}}//析构inline String::~String(){delete[] m_data;//一定要杀掉删除}//拷贝构造inline String::String(const String& str){m_data = new char[ strlen(str.m_data) + 1 ];//深拷贝strcpy(m_data, str.m_data);}//拷贝赋值inline String& String::operator=(const String& str){if (this == &str)//一定要检测自我赋值,可能指向同一个空间return *this;delete[] m_data;//搭配 array newm_data = new char[ strlen(str.m_data) + 1 ];strcpy(m_data, str.m_data);return *this;}

7、(stack)栈、(heap)堆与内存管理

Stack是存在于某作用域(scope)的一块内存空间(memory space)。(离开作用域,系统会自动清理!)

例如当你调用函数,函数本身即会形成一个stack用来放置它所接受的参数,以及返回地址;在函数本体(function body)内声明的任何变量,其所使用的内存块都取自上述的stack。

Heap,或谓 system heap, 是指由操作系统提供的一块 global内存空间,程序可动态分配(dynamic allocated),使用new创建,从某中获得若干区块(blocks)。(此开辟的空间使用完,需要我们手动释放delete,不然会内存泄漏!)

8、new: 先分配 memory , 再调用构造函数

Complex* pc = new Complex(1,2);

编译器转化为:

Complex *pc;

void* mem = operator new( sizeof(Complex) ); //第一步、分配內存(new 其内部调用malloc(n))pc = static_cast<Complex*>(mem); //第二步、转型pc->Complex::Complex(1,2); //第三步、构造函数

8、delete: 先调用析构函数,再释放 memory

Complex* pc = new Complex(1,2);...delete pc;

编译器转化为:

Complex::~Complex(pc); // 第一步、析构函數operator delete(pc); //第二步、释放內存 (delete 其内部调用 free(pc))

9、静态变量要用静态函数调用。

class Account {public:static double m_rate; //只是声明,静态变量static void set_rate(const double& x) {m_rate = x; }//静态函数};double Account::m_rate = 8.0; //赋初值int main() {//调用static函数的方式有两种:Account::set_rate(5.0);//1、通过class name调用Account a;a.set_rate(7.0);//2、通过object调用}

推荐写法:

class A {public:static A& getInstance();setup() {... }private:A();A(const A& rhs);...};A& A::getInstance()//只有别人调用这个函数时,才会生成静态变量a,且只有一份{static A a;return a;}

10、class template, 类模板

template<typename T>class complex{public:complex (T r = 0, T i = 0): re (r), im (i){}complex& operator += (const complex&);T real () const {return re; }T imag () const {return im; }private:T re, im;friend complex& __doapl (complex*, const complex&);};//使用{complex<double> c1(2.5, 1.5);complex<int> c2(2, 6);...}

11、namespace

namespace std{...}

#include <iostream.h>using namespace std;int main(){cin << ...;cout << ...;return 0;}

12、Object Oriented Programming, Object Oriented Design(OOP, OOD)

面向对象类和类的关系:

Inheritance (继承)Composition (复合)Delegation (委托)

1)、Composition (复合),表示: has-a

queue拥有deque,左边(Container)拥有右边(Component)构造由内而外Container的构造函数首先调用Componentdefault构造函数,然后才执行自己。(红色部分编译器自动加的!)析构由外而内Container的析构函数首先执行自己,然后才调用Component的析构函数。

下面的设计模式为:Adapter

template <class T, class Sequence = deque<T>>class queue {//队列...protected :Sequence c;//底层容器public:// 以下完全利用 c 的操作函数完成bool empty() const {return c.empty(); }size_type size() const {return c.size(); }reference front() {return c.front(); }reference back() {return c.back(); }//void push(const value_type& x) {c.push_back(x); }void pop() {c.pop_front(); }}

等价于:

template <class T>class queue {...protected:deque<T> c; // 底層容器public:…}

2)、Delegation (委托)Composition by reference.(编译防火墙)

左边(Handle)(拥有指针)指向右边(Body),不是同时存在的,只有左边用到右边时,右边才存在。

左边(Handle)

// file String.hppclass StringRep;class String {public:String();String(const char* s);String(const String& s);String &operator=(const String& s);~String();. . . .private:StringRep* rep; // pimpl,指向右边的指针};

右边(Body)

// file String.cpp#include "String.hpp"namespace {class StringRep {friend class String;StringRep(const char* s);~StringRep();int count;char* rep;};}String::String(){... }...

3)、Inheritance (继承),表示is-a

继承最有价值的地方是和虚函数打通

struct _List_node_base//父类{_List_node_base* _M_next;_List_node_base* _M_prev;};template<typename _Tp>struct _List_node : public _List_node_base //子类{_Tp _M_data;};

base class 的 dtor,必须是virtual,否则会出现undefined behavior

构造由内而外Deriverd(子类)的构造函数首先调用Base(父类)的default构造函数,然后才执行自己。(红色部分编译器自动加的!)析构由外而内Deriverd(子类)的析构函数首先执行自己,然后才调用Base(父类)的析构函数。

13、Inheritance (继承) with virtual functions(虚函数)(成员变量继承占用内存,函数继承的是调用权

non-virtual 函数:你不希望derived class 重新定义(override, 覆写) 它.virtual 函数:你希望derived class 重新定义(override, 覆写) 它,且你对它已有默认定义pure virtual 函数:你希望derived class一定要重新定义(override 覆写)它,你对它没有默认定义

class Shape {public:virtual void draw( ) const = 0;//pure virtualvirtual void error(const std::string& msg);//impure virtualint objectID( ) const;//non-virtual...};class Rectangle: public Shape {... };class Ellipse: public Shape {... };

14、Inheritance(继承)+Composition(复合)关系下的构造和析构

构造由内而外Deriverd(子类)的构造函数首先调用Base(父类)的default构造函数,然后调用Componentdefault构造函数,然后才执行自己。(红色部分编译器自动加的!)析构由外而内Deriverd(子类)的析构函数首先执行自己,然后调用Component的析构函数,然后才调用Base(父类)的析构函数

14、Delegation(委托) + Inheritance(继承)关系下的构造和析构

Subject

class Subject{int m_value;vector<Observer*> m_views;public:void attach(Observer* obs){m_views.push_back(obs);}void set_val(int value){m_value = value;notify();}void notify(){for (int i = 0; i < m_views.size(); ++i)m_views[i]->update(this, m_value);}};

Observer(将来可能被继承)

class Observer{public:virtual void update(Subject* sub, int value) = 0;};

Prototype

Image

#include <iostream.h>enum imageType{LSAT, SPOT};class Image{public:virtual void draw() = 0;static Image *findAndClone(imageType);protected:virtual imageType returnType() = 0;virtual Image *clone() = 0;// As each subclass of Image is declared, it registers its prototypestatic void addPrototype(Image *image){_prototypes[_nextSlot++] = image;}private:// addPrototype() saves each registered prototype herestatic Image *_prototypes[10];static int _nextSlot;};Image *Image::_prototypes[];int Image::_nextSlot;// Client calls this public static member function when it needs an instance// of an Image subclassImage *Image::findAndClone(imageType type){for (int i = 0; i < _nextSlot; i++)if (_prototypes[i]->returnType() == type)return _prototypes[i]->clone();}

LandSatImage

class LandSatImage: public Image{public:imageType returnType() {return LSAT;}void draw() {cout << "LandSatImage::draw " << _id << endl;}// When clone() is called, call the one-argument ctor with a dummy argImage *clone() {return new LandSatImage(1);}protected:// This is only called from clone()LandSatImage(int dummy) {_id = _count++;}private:// Mechanism for initializing an Image subclass - this causes the// default ctor to be called, which registers the subclass's prototypestatic LandSatImage _landSatImage;// This is only called when the private static data member is initedLandSatImage() {addPrototype(this);}// Nominal "state" per instance mechanismint _id;static int _count;};// Register the subclass's prototypeLandSatImage LandSatImage::_landSatImage;// Initialize the "state" per instance mechanismint LandSatImage::_count = 1;

SpotImage

class SpotImage: public Image{public:imageType returnType() {return SPOT;}void draw() {cout << "SpotImage::draw " << _id << endl;}mage *clone() {return new SpotImage(1);}protected:SpotImage(int dummy) {_id = _count++;}private:SpotImage() {addPrototype(this);} static SpotImage _spotImage;int _id;static int _count;};SpotImage SpotImage::_spotImage;int SpotImage::_count = 1;// Simulated stream of creation requestsconst int NUM_IMAGES = 8;imageType input[NUM_IMAGES] ={LSAT, LSAT, LSAT, SPOT, LSAT, SPOT, SPOT, LSAT};

main

int main(){Image *images[NUM_IMAGES];// Given an image type, find the right prototype, and return a clonefor (int i = 0; i < NUM_IMAGES; i++)images[i] = Image::findAndClone(input[i]);// Demonstrate that correct image objects have been clonedfor (i = 0; i < NUM_IMAGES; i++)images[i]->draw();// Free the dynamic memoryfor (i = 0; i < NUM_IMAGES; i++)delete images[i];}

注:个人学习笔记,仅供学习参考, 如有不足,欢迎指正!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。