基础语法 数据类型
编译过程 编译型语言一般需要经历编译和链接的过程,才能变成真正可执行的程序
标识符
关键字
常量
杂项运算符
字节序 一般的家用电脑是小端法
补码
右移运算
数组
字符串
字符串的指针表示方法
字符串常见操作
strlen()求字符串有效长度,不包括’\0’
1 2 char a[] = "123" ;cout << strlen (a) << endl;
sizeof()求字符串占用空间,包括’\0’
1 2 char a[] = "123" ;cout << sizeof (a) << endl;
strcmp(s1, s2)比较s1和s2的大小,逐个字符按照ASCII码比较
1 2 3 4 5 6 char a[] = "A" ;char b[] = "B" ;char c[] = "B" ;cout << strcmp (a, b) << endl; cout << strcmp (b, a) << endl; cout << strcmp (b, c) << endl;
strcpy(s1, s2)复制字符串s2到s1
strncpy(s1, s2, n)指定字符串长度复制
1 2 3 4 5 6 7 8 9 char a[100 ] = { 0 };char b[] = "hello" ;char c[] = "world" ;strcpy (a, b);cout << a << endl; strcpy (a, b);cout << a << endl; strncpy (a, c, 1 );cout << a << endl;
strcat(s1, s2)字符串拼接,将s2接到s1后面
strchr(s1, ch)指向字符串s1中ch第一次出现的位置
1 2 3 char a[] = "A" ;char b[] = "ABC" ;cout << strchr (b, 'B' ) << endl;
strstr(s1, s2)指向字符串s1中字符串s2第一次出现的位置
1 2 3 char a[] = "A" ;char b[] = "ABC" ;cout << strstr (b, a) << endl;
安全版避免缓冲区溢出
strcpy_s()是安全版strcpy()
strcat_s()是安全版strcat
strnlen_s()
strncpy_s()
常见bug
新型字符串string
相关函数 获取字符串长度:
s.lenth()
s.size()
s.capacity()默认容量是15
string转换为字符数组
s.c_str()
1 2 3 4 string s = "123" ; string s1 = "456" ; const char *c = s.c_str ();cout << c << endl;
指针/引用 指针就使用->,对象就使用.运算符
指针的定义和间接访问
数组与指针
左值与右值
几种原始指针 数组指针和指针数组
const与指针
指向指针的指针
未初始化和非法指针
NULL指针
野指针
原始指针的基本运算 指针默认是一个16字节的整型数,例如 char* 就是一个16字节的整型数,int* 也是
1 2 3 4 char b = '1' ;char * c = &b;*c = 'b' ; cout << *c << endl;
指针++,–的汇编 eax和ecx是寄存器
以char* cp2 = ++cp; 为例子
汇编的意思是:
将cp指针的值,放到eax寄存器里面
将eax寄存器里面的值+1
将eax的值存回cp
将cp的值存到ecx寄存器
将ecx寄存器的值存到cp2中
反汇编 打断点,f5运行的时候,右击鼠标,可以转到反汇编
c++存储区域划分 每行代码在内存环境中的具体位置
栈中的空间是从大地址往小地址分配的,先定义的变量,地址越大
堆中空间是从小往大分配的
字符串在常量区,变量在栈区,常量区的信息是不能改变的
堆
RAII
堆对比栈
静态存储区对比常量存储区
内存泄漏
比指针更安全的解决方案 智能指针
auto_ptr 1 2 auto_ptr<int > pl (new int (10 )) ;cout << *pl << endl;
unique_ptr
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <iostream> #include <memory> using namespace std;int main () { auto w = std::make_unique <int >(10 ); cout << *(w.get ()) << endl; auto w2 = std::move (w); cout << (w.get () != nullptr ? *(w.get ()) : -1 ) << endl; cout << (w2.get () != nullptr ? *(w2.get ()) : -1 ) << endl; return 0 ; }
1 2 3 4 5 { auto i = unique_ptr <int >(new int (10 )); }
shared_ptr
引用计数可能的bug: 循环引用会导致堆里的内存无法正常回收,造成内存泄漏
weak_ptr weak_ptr被设计为与shared_ptr共同工作,用一种观察者模式工作
引用
断言assert
有了指针为什么还需要引用 Bjarne Stroustrup的解释:为了支持函数运算符重载
有了引用为什么还需要指针 Bjarne Stroustrup的解释:为了兼容C语言
基础句法 switch与if 从汇编代码来看,多分支的switch的效率会比if更高一些
枚举 声明的时候,没有实际的空间存储它
但是当定义wT weekday;的时候,就会分配实际的空间存储它了
1 2 3 4 5 6 7 8 9 10 11 12 13 int main () { enum wT { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }; wT weekday; weekday = Monday; weekday = Tuesday; cout << weekday << endl; int a = Wednesday; cout << a << endl; return 0 ; }
结构体与联合体 结构体的数据对齐问题
结构体的内存布局 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 int main () { union Score { double ds; char level; }; struct Student { char name[6 ]; int age; Score s; }; cout << sizeof (Score) << endl; Student s1; strcpy_s (s1.name, "lili" ); s1.age = 16 ; s1.s.ds = 95.5 ; s1.s.level = 'A' ; cout << sizeof (Student) << endl; return 0 ; }
结构体的内存一定是其中最大的元素的整数倍
内存布局不是紧密的
头文件上加#pragma pack(1)可以让内存分配紧密相连
函数 函数名和参数列表一起构成了函数签名
例如:int(*p)(int, int);
,这行代码定义了一个可以指向返回值为整型且有两个整型形参函数的指针变量p,符合返回值为整型且有两个整型形参的函数都可以将其地址(即其函数名)赋给p。
在使用指向函数的指针变量时,只需要将函数名赋给指向函数的指针变量即可,因为函数名就是该函数的入口地址 。
由于指向函数的指针变量保存了函数的地址,则该指针变量就指向了对应的函数。例如,求最大值的函数命名为max
,如果将其函数名赋给指向函数的指针变量p
(即p = max
)后,则p
就指向了max
函数,并且可以通过(*p)(a, b);
的方式来调用max
函数,因为指针变量p
保存了max
函数的地址,那么*p
就是max
。需要注意的是,其中*p
前的*
可以省略,故也可以写成p(a, b);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #include <iostream> using namespace std;int MaxValue (int x, int y) { return (x > y) ? x : y; } int MinValue (int x, int y) { return (x < y) ? x : y; } int Add (int x, int y) { return x + y; } bool ProcessNum (int x, int y, int (*p)(int a, int b)) { cout << p (x, y) << endl; return true ; } int main () { int x = 10 , y = 20 ; cout << ProcessNum (x, y, MaxValue) << endl; cout << ProcessNum (x, y, MinValue) << endl; cout << ProcessNum (x, y, Add) << endl; return 0 ; }
命名空间
声明函数:在stdafx.h中
定义函数:在stdafx.cpp中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <iostream> using namespace std;int main () { int (*p)(int ); p = test; int result = (*p)(1 ); cout << result << endl; result = quickzhao::test (1 ); cout << result << endl; return 0 ; }
内联函数
先用vs设置一下:
但是编译器有可能不会用内联
递归
面向对象(实现Complex)
新建一个类:
构造函数与析构函数 ConsoleApplication1项目为完整代码
下面是以Complex复数为例,实现运算操作:
函数的声明在Complex.h文件中,实现在Complex.cpp文件中
默认构造函数:如果没有自己指定有参构造,系统则会自动创建默认构造函数
有参构造函数:如果自定义了有参构造,那么就需要显示的写出默认构造函数
声明:
1 2 3 4 5 6 7 class Complex { public : Complex (); Complex (double r, double i); virtual ~Complex (); }
实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Complex::Complex () { _real = 0.0 ; _image = 0.0 ; cout << "Complex::Complex()" << endl; } Complex::Complex (double r, double i) { _real = r; _image = i; cout << "Complex::Complex(double r, double i)" << endl; } Complex::~Complex () { cout << "Complex::~Complex()" << endl; }
运算符重载 一种重载 “+“ 的写法:
拷贝构造与临时对象
声明:
1 2 3 4 Complex operator + (const Complex& x); Complex (const Complex& x);
实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Complex Complex::operator + (const Complex& x) { Complex tmp; tmp._real = _real + x._real; tmp._image = _image + x._image; return tmp; } Complex::Complex (const Complex& x) { _real = x._real; _image = x._image; cout << "Complex::Complex(const Complex& x)" << endl; }
另一种重载 “+“ 的写法:
尽量避开临时变量和拷贝构造
声明:
1 2 Complex operator + (const Complex& x);
实现:
1 2 3 4 5 Complex Complex::operator + (const Complex& x) { return Complex (_real + x._real, _image + x._image); }
重载 ”=“ 的写法:
声明:
1 Complex& operator = (const Complex& x);
实现:
1 2 3 4 5 6 7 Complex& Complex::operator = (const Complex& x) { _real = x._real; _image = x._image; return *this ; }
临时对象与拷贝构造 栈上面的临时对象,返回的时候会触发一个拷贝构造,传回的不是栈中的对象,而是副本对象
返回的时候应该尽量避免临时对象的产生
前置后置++与– 前置++:先将变量自增,然后将值返回
后置++:先将值返回,然后将变量自增
声明:
1 2 3 Complex& operator ++ (); Complex operator ++ (int );
实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Complex& Complex::operator ++ () { _real++; _image++; return *this ; } Complex Complex::operator ++ (int ) { }
优化:避免拷贝构造
1 2 3 4 5 6 7 8 9 10 11 12 13 Complex Complex::operator ++ (int ) { return Complex (_real++, _image++); }
标准输入输出IO重载 friend关键字可以让大括号之外也能访问private的变量
声明:
1 2 3 4 5 friend ostream& operator <<(ostream& os, const Complex& x);friend istream& operator >>(istream& is, Complex& x);
实现:
1 2 3 4 5 6 7 8 9 10 11 12 ostream& operator <<(ostream& os, const Complex& x) { os << "real value is " << x._real << " image value is " << x._image; return os; } istream& operator >>(istream& is, Complex& x) { is >> x._real >> x._image; return is; }
目前为止完整代码 Complex.h:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #pragma once #include <iostream> using namespace std;class Complex { public : Complex (); Complex (double r, double i); virtual ~Complex (); Complex (const Complex& x); double getReal () const { return _real; } void setReal (double d) { _real = d; } double getImage () const { return _image; } void setImage (double i) { _image = i; } Complex operator + (const Complex& x); Complex& operator = (const Complex& x); Complex& operator ++ (); Complex operator ++ (int ); friend ostream& operator <<(ostream& os, const Complex& x); friend istream& operator >>(istream& is, Complex& x); private : double _real; double _image; };
Complex.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 #include "stdafx.h" #include "Complex.h" Complex::Complex () { _real = 0.0 ; _image = 0.0 ; } Complex::Complex (double r, double i) { _real = r; _image = i; } Complex::~Complex () { } Complex Complex::operator + (const Complex& x) { return Complex (_real + x._real, _image + x._image); } Complex& Complex::operator = (const Complex& x) { _real = x._real; _image = x._image; return *this ; } Complex::Complex (const Complex& x) { _real = x._real; _image = x._image; } Complex& Complex::operator ++ () { _real++; _image++; return *this ; } Complex Complex::operator ++ (int ) { return Complex (_real++, _image++); } ostream& operator <<(ostream& os, const Complex& x) { os << "real value is " << x._real << " image value is " << x._image; return os; } istream& operator >>(istream& is, Complex& x) { is >> x._real >> x._image; return is; }
ConsoleApplication1.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include "stdafx.h" #include "Complex.h" #include <iostream> #include <cstring> using namespace std;int main () { Complex a (3.0 , 2.0 ) ; Complex b (2.0 , 3.0 ) ; Complex c = a + b; Complex d (c) ; Complex e; e = d++; cout << e << endl; cout << d << endl; e = ++d; cout << e << endl; cout << d << endl; cin >> e; cout << e << endl; return 0 ; }
重载+= 声明:
1 Complex& operator += (const Complex& x);
定义:
1 2 3 4 5 6 Complex& Complex::operator += (const Complex& x) { _real += x._real; _image += x._image; return *this ; }
重载== 声明:
1 bool operator ==(const Complex& x);
定义:
1 2 3 4 bool Complex::operator ==(const Complex& x){ return (_real == x._real && _image == x._image); }
重载!= 声明:
1 bool operator !=(const Complex& x);
定义:
1 2 3 4 bool Complex::operator !=(const Complex& x){ return !(_real == x._real && _image == x._image); }
完整代码: Complex.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #pragma once #include <iostream> using namespace std;class Complex { public : Complex (); Complex (double r, double i); virtual ~Complex (); Complex (const Complex& x); double getReal () const { return _real; } void setReal (double d) { _real = d; } double getImage () const { return _image; } void setImage (double i) { _image = i; } Complex operator + (const Complex& x) const ; Complex& operator = (const Complex& x); Complex& operator += (const Complex& x); bool operator ==(const Complex& x); bool operator !=(const Complex& x); Complex& operator ++ (); Complex operator ++ (int ); friend ostream& operator <<(ostream& os, const Complex& x); friend istream& operator >>(istream& is, Complex& x); private : double _real; double _image; };
Complex.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 #include "stdafx.h" #include "Complex.h" Complex::Complex () { _real = 0.0 ; _image = 0.0 ; } Complex::Complex (double r, double i) { _real = r; _image = i; } Complex::~Complex () { } Complex Complex::operator + (const Complex& x) const { return Complex (_real + x._real, _image + x._image); } Complex& Complex::operator = (const Complex& x) { _real = x._real; _image = x._image; return *this ; } Complex& Complex::operator += (const Complex& x) { _real += x._real; _image += x._image; return *this ; } bool Complex::operator ==(const Complex& x){ return (_real == x._real && _image == x._image); } bool Complex::operator !=(const Complex& x){ return !(_real == x._real && _image == x._image); } Complex::Complex (const Complex& x) { _real = x._real; _image = x._image; } Complex& Complex::operator ++ () { _real++; _image++; return *this ; } Complex Complex::operator ++ (int ) { return Complex (_real++, _image++); } ostream& operator <<(ostream& os, const Complex& x) { os << "real value is " << x._real << " image value is " << x._image; return os; } istream& operator >>(istream& is, Complex& x) { is >> x._real >> x._image; return is; }
ConsoleApplication1.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include "stdafx.h" #include "Complex.h" #include <iostream> #include <cstring> using namespace std;int main () { Complex a (3.0 , 2.0 ) ; Complex b (2.0 , 3.0 ) ; Complex c = a + b; Complex d (c) ; Complex e; e = d++; cout << e << endl; cout << d << endl; e = ++d; cout << e << endl; cout << d << endl; cout << (e == d) << endl; cout << (e != a) << endl; cin >> e; cout << e << endl; e += a; cout << e << endl; return 0 ; }
IO流
IO缓存区
1 2 3 清空缓存区中的脏数据cin.ignore (要清空缓存区的字节数,以什么符号结尾) numeric_limits<std::streamsize>::max ()为缓存区的最大范围 cin.ignore (numeric_limits<std::streamsize>::max (), '\n' );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #include <iostream> using namespace std;int main () { int a; int index = 0 ; while (cin >> a) { cout << "the numbers are: " << a << endl; index++; if (index == 5 ) { break ; } } cin.ignore (numeric_limits<std::streamsize>::max (), '\n' ); char ch; cin >> ch; cout << "the last char is: " << ch << endl; return 0 ; }
文件操作
文件打开方式
以默认(覆盖)的方式打开 1 2 fout.open ("testBuffer.txt" );
open()方法,默认是以ios::in和ios::out的方式打开
如果文件不存在,不会自动帮我们创建一个文件
写入不是一种追加的方式,而是会覆盖原有内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include "stdafx.h" #include <iostream> #include <fstream> using namespace std;int main () { int a; int index = 0 ; fstream fout; fout.open ("testBuffer.txt" ); if (fout.fail ()) { cout << "open file failed" << endl; } while (cin >> a) { fout << "The numbers are: " << a << endl; index++; if (index == 5 ) { break ; } } cin.ignore (numeric_limits<std::streamsize>::max (), '\n' ); char ch; cin >> ch; fout << "The last char is: " << ch << endl; fout.close (); return 0 ; }
检测文件是否打开失败 直接看是否打开失败:
1 2 3 4 5 if (fout.fail ()){ cout << "open file failed" << endl; }
也可以看文件流对象是否存在:如果文件不存在,也会打开失败
1 2 3 4 if (!fout){ cout << "open file failed" << endl; }
以追加的方式打开 在文件的尾部添加数据
如果文件不存在,会自动创建一个文件
1 2 fout.open ("testBuffer.txt" , ios::app);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 #include "stdafx.h" #include <iostream> #include <fstream> using namespace std;int main () { int a; int index = 0 ; fstream fout; fout.open ("testBuffer.txt" , ios::app); if (!fout) { cout << "open file failed" << endl; } while (cin >> a) { fout << "The numbers are: " << a << endl; index++; if (index == 5 ) { break ; } } cin.ignore (numeric_limits<std::streamsize>::max (), '\n' ); char ch; cin >> ch; fout << "The last char is: " << ch << endl; fout.close (); return 0 ; }
操作二进制文件 以拷贝一个MP3文件为例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 #include "stdafx.h" #include <iostream> #include <fstream> using namespace std;static const int bufferLen = 2048 ;bool CopyFile (const string& src, const string& dst) { ifstream in (src.c_str(), ios::in | ios::binary) ; ofstream out (dst.c_str(), ios::out | ios::binary | ios::trunc) ; if (!in || !out) { return false ; } char temp[bufferLen]; while (!in.eof ()) { in.read (temp, bufferLen); streamsize count = in.gcount (); out.write (temp, count); } in.close (); out.close (); return true ; } int main () { cout << CopyFile ("testcopyfile.mp3" , "testcopyfile2.mp3" ) << endl; return 0 ; }
操作结果:成功
头文件重复包含的问题
头文件可以全部放到stdafx.h文件中,防止头文件太乱:
深拷贝与浅拷贝
设计String 设计String,实现拷贝构造和赋值运算符为深拷贝;并且设计String的移动构造函数和移动赋值运算符,使其满足移动语义
stdafx.h 1 2 3 4 5 6 7 8 9 10 11 12 13 #pragma once #include "targetver.h" #include <stdio.h> #include <tchar.h> #include <cstdlib> #include <string> #include <iostream> using namespace std;#include "String.h"
String.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #pragma once class String { public : String (const char *str = NULL ); String (const String &other); String (String&& other); ~String (void ); String& operator = (const String& other); String& operator =(String&& rhs)noexcept ; friend ostream& operator <<(ostream& os, const String &c); private : char *m_data; };
String.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 #include "stdafx.h" String::String (const char *str) { if (str == NULL ) { m_data = new char [1 ]; if (m_data != NULL ) { *m_data = '\0' ; } else { exit (-1 ); } } else { int len = strlen (str); m_data = new char [len + 1 ]; if (m_data != NULL ) { strcpy (m_data, str); } else { exit (-1 ); } } } String::String (const String &other) { int len = strlen (other.m_data); m_data = new char [len + 1 ]; if (m_data != NULL ) { strcpy (m_data, other.m_data); } else { exit (-1 ); } } String::String (String&& other) { if (other.m_data != NULL ) { m_data = other.m_data; other.m_data = NULL ; } } String& String::operator = (const String &other) { if (this == &other) { return *this ; } delete [] m_data; int len = strlen (other.m_data); m_data = new char [len + 1 ]; if (m_data != NULL ) { strcpy (m_data, other.m_data); } else { exit (-1 ); } return *this ; } String& String::operator =(String&& rhs)noexcept { if (this != &rhs) { delete [] m_data; m_data = rhs.m_data; rhs.m_data = NULL ; } return *this ; } String::~String (void ) { if (m_data != NULL ) { delete [] m_data; } } ostream& operator <<(ostream& os, const String &c) { os << c.m_data; return os; }
demo.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include "stdafx.h" int main () { String s1 ("Hello" ) ; cout << s1 << endl; String s2 (s1) ; cout << s2 << endl; String s2A (std::move(s1)) ; cout << s2A << endl; String s3; cout << s3 << endl; s3 = s2; cout << s3 << endl; String s3A; s3A = std::move (s2A); cout << s3A << endl; return 0 ; }
移动语义
移动语义:设计在String的移动构造函数和移动赋值运算符中
面向对象(继承与多态) 子类方法和父类实现不一样,则要在父类的这个方法上加上vitual
子类的对象里面保存了什么? 子类的对象里面保存了什么?
自己的变量
父类的变量
还有一个指向虚表的指针(4个字节),虚表里面包含了父类虚函数的地址
注意:对象模型中,不保存一般的函数地址,只保留成员变量的信息和虚函数的虚表
this指针底层原理 一般函数能够引用到成员变量的变量信息和虚函数的信息,是因为一般函数能找到对象的地址
一般函数是通过this指针找到的对象地址,this指针指向对象本身
this指针很多时候就是通过ecx这个寄存器进行传递的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 #include "stdafx.h" #include <iostream> using namespace std;class Shape { public : virtual double Area () const = 0 ; void Display () { cout << Area () << endl; } }; class Square :public Shape{ public : Square (double len):_len(len){} double Area () const { return _len * _len; } private : double _len; }; class Circle :public Shape{ public : Circle (double radius):_radius(radius){} double Area () const { return 3.1415926 * _radius * _radius; } private : double _radius; }; class Triangle :public Shape{ public : Triangle (double len, double height):_len(len), _height(height){} double Area () const { return 0.5 * _len * _height; } private : double _len; double _height; }; int main () { Square s1 (2.0 ) ; Circle c1 (2.0 ) ; Triangle t1 (2.0 , 3.0 ) ; Shape* shapes[3 ]; shapes[0 ] = &s1; shapes[1 ] = &c1; shapes[2 ] = &t1; for (unsigned int index = 0 ; index < 3 ; index++) { shapes[index]->Display (); } return 0 ; }
C++编程思想 单例模式 实现思路:
Singleton拥有一个私有构造函数,确保用户无法通过new直接实例它
包含一个静态私有成员变量instance与静态公有方法instance()
Singleton.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #pragma once #include <iostream> using namespace std;class Singleton { public : static const Singleton* getInstance () ; static void DoSomething () { cout << "Do Something" << endl; } private : Singleton (); ~Singleton (); static Singleton* This; };
Singleton.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include "stdafx.h" #include "Singleton.h" Singleton* Singleton::This = NULL ; const Singleton* Singleton::getInstance () { if (!This) { This = new Singleton (); } return This; } Singleton::Singleton () { } Singleton::~Singleton () { }
demo.cpp 1 2 3 4 5 6 7 8 9 10 11 #include "stdafx.h" #include "Singleton.h" int main () { Singleton::getInstance ()->DoSomething (); return 0 ; }
观察者模式 在观察者模式中,观察者需要直接订阅目标事件;在目标发出内容改变的事件后,直接接收事件并作出响应,对象常是一对多关系
常见场景:各种MVC的框架中,Model的变化通知各种类型的View时几乎都存在这种模式
实现思路:将问题的职责解耦合,将Observable和Observer抽象开,分清抽象和实体