GitHub Repo:coderZsq.github.io
Follow: coderZsq · GitHub
Resume: https://coderzsq.github.io/coderZsq.webpack.js/#/
日常扯淡
明天就要出国了, 所以本来想将.md的旅行攻略放到网上共享的, 就使用了简书的.md编译器, 没想到的是, 用完之后我的账号就被冻结了….
尊敬的简书用户您好,由于您有可能违反了简书社区管理规定(包括但不仅限于违反法律法规,不友善行为,发布垃圾信息,恶意行为如简信滋扰),具体可查看《「简书」指导原则和管理细则》http://dwz.cn/3BcYrg 和《简书社区指导规则》http://dwz.cn/3BcZi1 ,现根据情节严重程度,给予您冻结账户的惩罚,冻结期间帐号无法发表和编辑任何内容,您的数据将会为您保留60天,在此期间您可以备份您的文章,钱包里如有余额可及时提现,如您对结果处理有异议,也可联系邮箱 help@jianshu.com ,60天后将会直接注销您的账号并删除所有数据
真是的… 现在简书给我的印象是越来越差了, 随随便便写一点水文都有上千的阅读量, 而现在那个事件之后, 许多大佬的出走, 简书也可能对程序员这个群体不再重视了吧, 所以以后的文章会陆续发在掘金上. 简书的账号可能会在60天之后被删除吧… 也无所谓了…反正我已经全部迁移到githubpages上去了. 有兴趣的同学可以star
关注.
上周我们就简单了解了, C
和C++
之间的差异为切入点, 而有了上周的基础, 这次, 我们就能够更加深入的理解OC
的底层实现原理了.
C++ 作者的建议
- 在C++中几乎不需要用宏, 用const和enum定义显式的常量, 用inline避免函数调用的额外开销, 用模板去刻画一组函数或类型, 用namespace去避免命名冲突.
- 不要在你需要变量之前去声明, 以保证你能立即对它进行初始化.
- 不要用malloc, new运算会做的更好.
- 避免使用void*, 指针算数, 联合和强制, 大多数情况下, 强制类型转换是设计错误的指示器.
- 尽量少用数组和C风格的字符串, 标准库中的string和vector可以简化程序.
- 更加重要的是, 试着将程序考虑为一组由类和对象表示的互相作用的概念年, 而不是一堆数据结构和一些可以拨弄的二进制.
自实现 string
string
本质其实就是对char *
的包装, 而NSString
也是如此.
int sq_strlen(const char * str) {
int len = 0;
while (*str++)
len++;
return len;
}
char * sq_strcpy(char * dst, const char * src) {
char * d = dst;
while ((*dst++ = *src++));
return d;
}
int sq_strcmp(const char * str1, const char * str2) {
for (; *str1 && *str2; str1++, str2++) {
if (*str1 == *str2) {
continue;
} else {
return *str1 - *str2;
}
}
return *str1 - *str2;
}
char * sq_strcat(char * dst, const char * src) {
char * d = dst;
while (*dst)
dst++;
while ((*dst++ = *src++));
return d;
}
我们先来自实现一下<string.h>
中的常用方法, 代码公开了, 我就不细讲原理了, 自己多试试应该就能够有所领悟.
class SQString {
public:
SQString(const char * str = nullptr);
SQString(const SQString & another);
SQString& operator=(const SQString & another);
bool operator==(const SQString & another);
bool operator>(const SQString & another);
bool operator<(const SQString & another);
bool operator>=(const SQString & another);
bool operator<=(const SQString & another);
SQString operator+(const SQString & another);
SQString& operator+=(const SQString & another);
~SQString();
char at(int n);
char operator[](int n);
char * c_str();
void description();
private:
char * _str;
};
猜测string
内部实现原理, 其实就是构造器, 拷贝构造器, 运算符重载, 和一些常用函数的封装罢了, 并没有什么很神奇的东西.
SQString::SQString(const char * str) {
if (str == nullptr) {
_str = new char[1];
*_str = '\0';
} else {
_str = new char[sq_strlen(str) + 1];
sq_strcpy(_str, str);
}
}
SQString::SQString(const SQString & another) {
_str = new char[sq_strlen(another._str) + 1];
sq_strcpy(_str, another._str);
}
SQString& SQString::operator=(const SQString & another) {
if (this == &another) {
return *this;
}
delete []this->_str;
_str = new char[sq_strlen(another._str) + 1];
sq_strcpy(_str, another._str);
return *this;
}
bool SQString::operator==(const SQString & another) {
return sq_strcmp(this->_str, another._str) == 0;
}
bool SQString::operator>(const SQString & another) {
return sq_strcmp(this->_str, another._str) > 0;
}
bool SQString::operator<(const SQString & another) {
return sq_strcmp(this->_str, another._str) < 0;
}
bool SQString::operator>=(const SQString & another) {
return sq_strcmp(this->_str, another._str) >= 0;
}
bool SQString::operator<=(const SQString & another) {
return sq_strcmp(this->_str, another._str) <= 0;
}
SQString SQString::operator+(const SQString & another) {
int len = sq_strlen(this->_str) + sq_strlen(another._str);
SQString str;
delete []str._str;
str._str = new char[len + 1]{0};
sq_strcat(sq_strcat(str._str, this->_str), another._str);
return str;
}
SQString& SQString::operator+=(const SQString & another) {
int catLen = sq_strlen(this->_str);
int srcLen = sq_strlen(another._str);
int len = catLen + srcLen;
this->_str = (char *)realloc(this->_str, len + 1);
memset(this->_str + catLen, 0, srcLen + 1);
sq_strcat(this->_str, another._str);
return *this;
}
SQString::~SQString() {
cout<<"delete: "<<this<<endl;
delete []_str;
}
char SQString::at(int n) {
return _str[n];
}
char SQString::operator[](int n) {
return _str[n];
}
void SQString::description() {
cout<<_str<<endl;
}
char * SQString::c_str() {
return _str;
}
上面就是一些string
的基础实现方式, 并没有超出上篇文章所涉及的范畴, 简单易理解, 对我们以后看runtime
源码会有帮助.
int main(int argc, const char * argv[]) {
SQString * s = new SQString;
SQString * s1 = new SQString("Castiel");
SQString * s2 = new SQString(*s1);
SQString s3 = *s = *s1;
SQString s4 = *s1 + SQString(" is perpect!");
SQString s5 = SQString("Tell a joke: ") += s4;
cout<<"s: "; s->description();
cout<<"s1: "; s1->description();
cout<<"s2: "; s2->description();
cout<<"s3: "; s3.description();
cout<<"s4: "; s4.description();
cout<<"s5: "; s5.description();
if (*s == s3) {
cout<<"*s == s3"<<endl;
}
if (*s2 >= s3) {
cout<<"*s2 >= s3"<<endl;
}
if (*s < SQString("abc")) {
cout<<"*s < SQString(\"abc\")"<<endl;
}
cout<<"s5.at(2): "<<s5.at(2)<<endl;
cout<<"s5[5]: "<<s5[5]<<endl;
cout<<"s5.c_str(): "<<s5.c_str()<<endl;
cout<<"sizeof(SQString) : "<<sizeof(SQString)<<endl;
delete s;
delete s1;
delete s2;
return 0;
}
我们来用自实现的想系统的string
一样使用, 会感觉并无差别.
delete: 0x7ffeefbff560
delete: 0x7ffeefbff550
s: Castiel
s1: Castiel
s2: Castiel
s3: Castiel
s4: Castiel is perpect!
s5: Tell a joke: Castiel is perpect!
*s == s3
*s2 >= s3
delete: 0x7ffeefbff548
*s < SQString("abc")
s5.at(2): l
s5[5]: a
s5.c_str(): Tell a joke: Castiel is perpect!
sizeof(SQString) : 8
delete: 0x100419ad0
delete: 0x100404b60
delete: 0x100403f40
delete: 0x7ffeefbff558
delete: 0x7ffeefbff568
delete: 0x7ffeefbff570
Program ended with exit code: 0
使用起来还是如此的自然, 当然, 自实现只是让我们更好的了解本质, 并不是要使用自实现的东西, 而重复造轮子炫技.
const
接下来, 我们来说说const
, const
这个东西非常的厉害, 比如 int const * a
, 和 int * const a
就是完全两个概念, 这在上一篇文章里也有说到了, 这次我们来看下const
在类中的表述.
struct A
{
public:
A(int x, int y, int & z):_x(x), _y(y), _z(z) {
cout<<"const x: "<<_x<<endl;
cout<<" y: "<<_y<<endl;
cout<<" z: "<<_z<<endl;
}
private:
const int _x;
int _y;
int & _z;
};
int main(int argc, const char * argv[]) {
int z = 300;
A a(100, 200, z);
return 0;
}
const x: 100
y: 200
z: 300
Program ended with exit code: 0
在类中const
与 初始化列表的使用, 可以使用初始化列表为const
变量初始化.
int add(int & a, int & b) {
return a + b;
}
int add(const int & a, const int & b) {
return a + b;
}
int main(int argc, const char * argv[]) {
int a = 3; int b = 5;
cout<<add(a, b)<<endl;
cout<<add(4, 6)<<endl;
return 0;
}
8
10
Program ended with exit code: 0
使用const
可以在传递参数的时候, 重载常量引用.
class A {
public:
A(int x, int y):_x(x), _y(y) {}
void foo();
void foo() const;
private:
int _x;
int _y;
};
void A::foo() {
_x = 300;
cout<<"non-const : "<<_x<<_y<<endl;
}
void A::foo() const {
cout<<"const: "<<_x<<_y<<endl;
}
int main(int argc, const char * argv[]) {
const A a(3, 4);
a.foo();
A a1(5, 6);
a1.foo();
return 0;
}
const: 34
non-const : 3006
Program ended with exit code: 0
总结一下:
const
修饰函数以后, 承诺, 不改变, 在本函数不会发生改变数据成员的行为.
const
构成的重载函数, 非const
对象, 优先调用非const
版本.
const
对象, 只能调用const
版本的函数. 很多库常见提供两个版本.
const
修饰的对象, 其内可以有非const
数据成员, 但不可修改. 只能调用const
成员函数.
static
接下来, 我们来说说static
, static
是全局的存储在代码段的rw
段, 我们平时的场景比如在 cell
的标识符的引用, static const
代替宏, gcd单例
等等.
class A {
public:
int _m = 0, _n = 0;
static int _share;
};
int A::_share = 100;
int main(int argc, const char * argv[]) {
A a;
cout<<a._n<<endl;
cout<<a._m<<endl;
cout<<a._share<<endl;
cout<<A::_share<<endl;
return 0;
}
0
0
100
100
Program ended with exit code: 0
static
修饰数据成员, 需要初始化, 不可以类内初始化.
类外初始化, 需要类名空间, 且不需要static
.
static
声明的数据成员, 不占用类的大小, 存储在data rw
段.
class A {
public:
~A();
void foo();
int _m = 0, _n = 0;
static int _fooCount;
};
int A::_fooCount = 0;
A::~A() {
cout<<"dealloc"<<endl;
}
void A::foo() {
cout<<"void foo()"<<endl;
_fooCount++;
}
int main(int argc, const char * argv[]) {
{
A a,b,c;
a.foo();
b.foo();
c.foo();
}
cout<<A::_fooCount<<endl;
return 0;
}
void foo()
void foo()
void foo()
dealloc
dealloc
dealloc
3
Program ended with exit code: 0
class A {
public:
~A();
void foo();
static int invokeFooCount();
private:
int _m = 0, _n = 0;
static int _fooCount;
};
int A::_fooCount = 0;
A::~A() {
cout<<"dealloc"<<endl;
}
void A::foo() {
cout<<"void foo()"<<endl;
_fooCount++;
}
int A::invokeFooCount() {
return _fooCount;
}
int main(int argc, const char * argv[]) {
{
A a,b,c;
a.foo();
b.foo();
c.foo();
cout<<a.invokeFooCount()<<endl;
}
cout<<A::invokeFooCount()<<endl;
return 0;
}
void foo()
void foo()
void foo()
3
dealloc
dealloc
dealloc
3
Program ended with exit code: 0
static修饰函数, 目的为管理静态变量.
class University {
public:
University(string t, string l);
static string & getLib();
void display();
private:
string _tower;
string _lake;
static string _lib;
};
string University::_lib = "";
University::University(string t, string l):_tower(t), _lake(l){}
string & University::getLib() {
return _lib;
}
void University::display() {
cout<<"tower: "<<_tower<<" lake: "<<_lake<<" lib: "<<_lib<<endl;
}
int main(int argc, const char * argv[]) {
University u1("tower1", "lake1");
University u2("tower2", "lake2");
University u3("tower3", "lake3");
University::getLib() += "lib1";
u1.display();
u2.getLib() += "lib2";
u2.display();
u3.getLib() += "lib3";
u3.display();
return 0;
}
tower: tower1 lake: lake1 lib: lib1
tower: tower2 lake: lake2 lib: lib1lib2
tower: tower3 lake: lake3 lib: lib1lib2lib3
Program ended with exit code: 0
static
共享
静态成员函数, 只能访问静态的成员. (数据成员和函数成员), 不能访问非静态的成员. 是因为非静态函数没有隐式传入this指针.
非静态函数访问静态函数式可以的.
singleton
单例, 这个非常简单, 对于有经验的iOS
开发者来说, 其实就会写一个单例的宏, 但我们还是要知道如何实现.
class Singleton {
public:
static Singleton * shareInstance();
static void releaseInstance();
private:
Singleton(){};
~Singleton(){};
Singleton(const Singleton & another){};
Singleton & operator=(const Singleton & another){return *this;};
static Singleton * _instance;
};
Singleton * Singleton::_instance = nullptr;
Singleton * Singleton::shareInstance() {
if (_instance == nullptr) {
_instance = new Singleton;
}
return _instance;
}
void Singleton::releaseInstance() {
if (_instance != NULL) {
delete _instance;
_instance = nullptr;
}
}
int main(int argc, const char * argv[]) {
Singleton * ps = Singleton::shareInstance();
Singleton * ps2 = Singleton::shareInstance();
Singleton * ps3 = Singleton::shareInstance();
cout<<ps<<endl;
cout<<ps2<<endl;
cout<<ps3<<endl;
Singleton::releaseInstance();
return 0;
}
0x100412a60
0x100412a60
0x100412a60
Program ended with exit code: 0
总结就是静态读取, 私有构造.
自实现 autoreleasepool
自动释放池这个概念对于我们做iOS
的并不会陌生吧, 接下来, 我们就来自实现一个简版的自动释放池, 当然这个版本并不会有引用计数的内容, 仅仅是内存托管的实现.
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
class SQObject {
public:
SQObject(){}
static SQObject * create() {
SQObject * obj = new SQObject();
if (obj && obj->init()) {
obj->autoRealease();
return obj;
} else {
delete obj;
obj = nullptr;
exit(-1);
}
}
bool init() {
cout<<"initial"<<endl;
ch = rand()%(127-32) + 33;
return true;
}
void autoRealease() {
// if (head == nullptr) {
// head = this;
// this->next = nullptr;
// } else {
// this->next = head;
// head = this;
// }
this->next = head;
head = this;
}
static void autoRealeasePool() {
SQObject * t = head;
while (t) {
cout<<"realease: "<<t->ch<<endl;
t = t->next;
}
}
private:
static SQObject * head;
SQObject * next;
char ch;
};
SQObject * SQObject::head = nullptr;
int main(int argc, const char * argv[]) {
srand(time(NULL));
for (int i = 0; i < 5; i++) {
SQObject * obj = SQObject::create();
}
SQObject::autoRealeasePool();
return 0;
}
initial
initial
initial
initial
initial
realease: n
realease: .
realease: ^
realease: i
realease: k
Program ended with exit code: 0
其实就和我们感觉上一样, 自动释放池用一个链表就可以解决, 当出了作用域的时候后, 将自动释放池链表中引用计数为0
的地址给赋值null
就完成了, 真是easy~
static const
这个我就不多说了, 大家日常使用都会有心得的东西.
class A {
public:
static const int a = 100;
};
int main(int argc, const char * argv[]) {
cout<<A::a<<endl;
return 0;
}
static const
存储在数据段的 ro
段;
pointer2class -> ivar & func
这一章会比较晦涩难懂些, 可以翻阅一下其他的文章, 其实就是如何通过指针来指向类内的成员变量及函数.
class Student {
public:
Student(string n, int nu):name(n), num(nu){}
void display(int idx) {
cout<<"idx "<<idx<<" name "<<name<<" num "<<num<<endl;
}
//private:
string name;
int num;
};
int main(int argc, const char * argv[]) {
Student s("Castiel", 1024);
Student * ps = &s;
Student ss("Aquas", 3328);
Student * pss = &ss;
string Student::* psn = &Student::name;
cout<<s.*psn<<endl;
cout<<ps->*psn<<endl;
cout<<ss.*psn<<endl;
cout<<pss->*psn<<endl;
void (Student::* pf)(int) = &Student::display;
(s.*pf)(1);
(ss.*pf)(2);
(ps->*pf)(3);
(pss->*pf)(4);
return 0;
}
Castiel
Castiel
Aquas
Aquas
idx 1 name Castiel num 1024
idx 2 name Aquas num 3328
idx 3 name Castiel num 1024
idx 4 name Aquas num 3328
Program ended with exit code: 0
关注void (Student::* pf)(int) = &Student::display;
和 string Student::* psn = &Student::name;
就可以了, 编译器固定格式.
科里化
通过上述的指针, 我们还可以实现科里化, 也就是喵神100tips
中的第一章内容的本质.
struct Point {
int add(int x, int y) {
return x + y;
}
int minus(int x, int y) {
return x - y;
}
int mul(int x, int y) {
return x * y;
}
int div(int x, int y) {
return x / y;
}
};
int oper(Point & p, int (Point::*pf)(int x, int y), int x, int y) {
return (p.*pf)(x, y);
}
typedef int (Point::*PF)(int, int);
int main(int argc, const char * argv[]) {
Point p;
PF pf = &Point::add;
pf = &Point::mul;
cout<<oper(p, pf, 5, 2)<<endl;
return 0;
}
10
Program ended with exit code: 0
隐蔽接口
更高级点的做法, 我们可以使用这个方法来隐藏接口, 这样别人在用我们做好的功能的时候, 就能傻瓜式的操作, 而隐蔽内部逻辑了.
class Game {
public:
Game() {
pf[0] = &Game::a;
pf[1] = &Game::b;
pf[2] = &Game::c;
pf[3] = &Game::d;
}
void select(int i) {
if (i >= 0 && i <= 3) {
(this->*pf[i])(i);
}
}
private:
void a(int idx){cout<<"void a(int idx)"<<idx<<endl;}
void b(int idx){cout<<"void b(int idx)"<<idx<<endl;}
void c(int idx){cout<<"void c(int idx)"<<idx<<endl;}
void d(int idx){cout<<"void d(int idx)"<<idx<<endl;}
enum {
nc = 4
};
void (Game::*pf[nc])(int idx);
};
int main(int argc, const char * argv[]) {
Game g;
g.select(1);
g.select(2);
g.select(3);
return 0;
}
void b(int idx)1
void c(int idx)2
void d(int idx)3
Program ended with exit code: 0
friend
友元, 其实就是一种便捷访问非本类私有方法的. 是对封装的破坏.
class Sprite {
friend void fight(Sprite & sp);
public:
Sprite(int lb = 100): _lifeBlood(lb){}
int getLifeBlood() {
return _lifeBlood;
}
void setLifeBlood(int lb) {
_lifeBlood = lb;
}
private:
int _lifeBlood;
};
void fight(Sprite & sp) {
// sp.setLifeBlood(sp.getLifeBlood() - 20);
// cout<<sp.getLifeBlood()<<endl;
sp._lifeBlood = sp._lifeBlood - 20;
cout<<sp._lifeBlood<<endl;
}
int main(int argc, const char * argv[]) {
Sprite sp;
fight(sp);
return 0;
}
class Complex {
friend Complex operator+(Complex & c1, Complex & c2);
public:
Complex(double r = 0, double i = 0): real(r), image(i) {}
void dumpFormat() {
cout<<"("<<real<<","<<image<<")"<<endl;
}
private:
double real;
double image;
};
Complex operator+(Complex & c1, Complex & c2) {
Complex c;
c.real = c1.real + c2.real;
c.image = c1.image + c2.image;
return c;
}
int main(int argc, const char * argv[]) {
Complex c1(1, 2);
Complex c2(3, 4);
Complex sum;
sum = c1 + c2;
sum.dumpFormat();
return 0;
}
声明为谁的友元, 就可以通过谁的对象, 访问谁的私有函数.
class Point {
friend float getDistance(Point & p1, const Point & p2);
public:
Point(int x = 0, int y = 0):_x(x), _y(y){}
void dumpFormat() {
cout<<"("<<_x<<","<<_y<<")"<<endl;
}
private:
float _x;
float _y;
};
float getDistance(const Point & p1, const Point & p2) {
float dx = p1._x - p2._x;
float dy = p1._y - p2._y;
return sqrt(dx * dx + dy * dy);
}
int main(int argc, const char * argv[]) {
Point p1(3, 4);
p1.dumpFormat();
Point p2(7, 8);
p2.dumpFormat();
cout<<"dis:"<<getDistance(p1, p2)<<endl;
return 0;
}
全局做friend 不受类的权限控制
class Point;
class ManagePoint {
public:
float getDistance(Point & p1, const Point & p2);
};
class Point {
friend float ManagePoint::getDistance(Point & p1, const Point & p2);
public:
Point(int x = 0, int y = 0):_x(x), _y(y){}
void dumpFormat() {
cout<<"("<<_x<<","<<_y<<")"<<endl;
}
private:
float _x;
float _y;
};
float ManagePoint::getDistance(const Point & p1, const Point & p2) {
float dx = p1._x - p2._x;
float dy = p1._y - p2._y;
return sqrt(dx * dx + dy * dy);
}
int main(int argc, const char * argv[]) {
Point p1(3, 4);
p1.dumpFormat();
Point p2(7, 8);
p2.dumpFormat();
ManagePoint mp;
cout<<"dis:"<<mp.getDistance(p1, p2)<<endl;
return 0;
}
前向声明的问题 前向声明, 是一种不完全类型的声明, 不能定义对象.
可以定义指针和引用 作参数和返回值, 仅用在函数声明中.
class Point {
friend class ManagePoint;
public:
Point(int x = 0, int y = 0):_x(x), _y(y){}
void dumpFormat() {
cout<<"("<<_x<<","<<_y<<")"<<endl;
}
private:
float _x;
float _y;
};
class ManagePoint {
public:
float getDistance(const Point & p1, const Point & p2) {
float dx = p1._x - p2._x;
float dy = p1._y - p2._y;
return sqrt(dx * dx + dy * dy);
}
};
int main(int argc, const char * argv[]) {
Point p1(3, 4);
p1.dumpFormat();
Point p2(7, 8);
p2.dumpFormat();
ManagePoint mp;
cout<<"dis:"<<mp.getDistance(p1, p2)<<endl;
return 0;
}
class Point {
friend class ManagePoint;
public:
Point(int x = 0, int y = 0):_x(x), _y(y){}
void dumpFormat() {
cout<<"("<<_x<<","<<_y<<")"<<endl;
}
private:
float _x;
float _y;
};
class ManagePoint {
public:
float getDistance(const Point & p1, const Point & p2) {
float dx = p1._x - p2._x;
float dy = p1._y - p2._y;
return sqrt(dx * dx + dy * dy);
}
float getArea(const Point & p1, const Point & p2, const Point & p3) {
float da = getDistance(p1, p2);
float db = getDistance(p2, p3);
float dc = getDistance(p3, p1);
float p = (da + db + dc) / 2;
return sqrt(p * (p - da) * (p - db) * (p - dc));
}
};
int main(int argc, const char * argv[]) {
Point p1(3, 4);
p1.dumpFormat();
Point p2(7, 8);
p2.dumpFormat();
Point p3(-100, 900);
ManagePoint mp;
cout<<"dis:"<<mp.getDistance(p1, p2)<<endl;
cout<<"area:"<<mp.getArea(p1, p2, p3)<<endl;
return 0;
}
友元类的使用, 可以避免前向声明的麻烦, 仅仅是提供便捷.
operator
运算符重载的使用, 和上篇一样, 这里更加深入.
class Complex {
public:
Complex(double r = 0, double i = 0):real(r), image(i){}
void dumpFormat() {
cout<<"("<<this->real<<","<<this->image<<")"<<endl;
}
Complex & operator= (const Complex & another) {
this->real = another.real;
this->image = another.image;
return *this;
}
const Complex operator+(const Complex & another) {
Complex sum;
sum.real = this->real + another.real;
sum.image = this->image + another.image;
return sum;
}
private:
double real;
double image;
};
int main(int argc, const char * argv[]) {
Complex a(1, 2), b(4, 5);
Complex s = a + b;
b.dumpFormat();
a.dumpFormat();
s.dumpFormat();
return 0;
}
class Complex {
public:
Complex(double r = 0, double i = 0):real(r), image(i){}
void dumpFormat() {
cout<<"("<<this->real<<","<<this->image<<")"<<endl;
}
Complex & operator +=(const Complex & another) {
this->real += another.real;
this->image += another.image;
return *this;
}
private:
double real;
double image;
};
int main(int argc, const char * argv[]) {
int a = 10, b = 20, c = 30;
a += b;
b += c;
cout<<"a: "<<a<<endl;
cout<<"b: "<<b<<endl;
cout<<"c: "<<c<<endl;
Complex ca(10, 0), cb(20, 0), cc(30, 0);
ca += cb; // plus return *this
cb += cc;
ca.dumpFormat();
cb.dumpFormat();
cc.dumpFormat();
int a1 = 10, b1 = 20, c1 = 30;
a1 += b1 += c1;
cout<<"a1: "<<a1<<endl;
cout<<"b1: "<<b1<<endl;
cout<<"c1: "<<c1<<endl;
Complex ca1(10, 0), cb1(20, 0), cc1(30, 0);
ca1 += cb1 += cc1; // plus const
ca1.dumpFormat();
cb1.dumpFormat();
cc1.dumpFormat();
int a2 = 10, b2 = 20, c2 = 30;
(a2 += b2) += c2;
cout<<"a2: "<<a2<<endl;
cout<<"b2: "<<b2<<endl;
cout<<"c2: "<<c2<<endl;
Complex ca2(10, 0), cb2(20, 0), cc2(30, 0);
(ca2 += cb2) += cc2; // plus &
ca2.dumpFormat();
cb2.dumpFormat();
cc2.dumpFormat();
return 0;
}
a: 30
b: 50
c: 30
(30,0)
(50,0)
(30,0)
a1: 60
b1: 50
c1: 30
(60,0)
(50,0)
(30,0)
a2: 60
b2: 20
c2: 30
(60,0)
(20,0)
(30,0)
Program ended with exit code: 0
class Complex {
public:
Complex(double r = 0, double i = 0):real(r), image(i){}
void dumpFormat() {
cout<<"("<<this->real<<","<<this->image<<")"<<endl;
}
const Complex operator-() const {
return Complex(-this->real, -this->image);
}
private:
double real;
double image;
};
int main(int argc, const char * argv[]) {
int n = 5;
// -n = 10;
cout<<-n<<endl;
cout<<n<<endl;
cout<<-(-n)<<endl;
Complex c(5, 0);
Complex c1 = -c;
// -cc = Complex(10, 0); //plus const
Complex c2 = -(-c); //plus func const
c1.dumpFormat();
c.dumpFormat();
c2.dumpFormat();
return 0;
}
-5
5
5
(-5,-0)
(5,0)
(5,0)
Program ended with exit code: 0
class Complex {
public:
Complex(double r = 0, double i = 0):real(r), image(i){}
void dumpFormat() const {
cout<<"("<<this->real<<","<<this->image<<")"<<endl;
}
Complex & operator++() {
this->real++;
this->image++;
return *this;
}
const Complex operator++(int) /*编译器的规则*/ {
Complex r(*this);
++this->real;
++this->image;
return r;
}
private:
double real;
double image;
};
int main(int argc, const char * argv[]) {
int a = 10;
cout<<++a<<endl;
cout<<a<<endl;
cout<<++++a<<endl;
cout<<a<<endl;
cout<<a++<<endl;
cout<<a<<endl;
// cout<<a++++<<endl;
Complex c(10, 0);
(++c).dumpFormat();
c.dumpFormat();
(++++c).dumpFormat();
c.dumpFormat();
(c++).dumpFormat();
c.dumpFormat();
return 0;
}
11
11
13
13
13
14
(11,1)
(11,1)
(13,3)
(13,3)
(13,3)
(14,4)
Program ended with exit code: 0
class Mail {
friend class Sender;
public:
Mail(string title, string contents):_title(title), _contents(contents){}
private:
string _title;
string _contents;
};
class Sender {
public:
Sender(string addr):_addr(addr){}
Sender & operator<<(const Mail & mail) {
cout<<mail._title<<endl;
cout<<mail._contents<<endl;
return *this;
}
private:
string _addr;
};
int main(int argc, const char * argv[]) {
Sender sender("github.com/coderzsq");
Mail mail("title1", "description1");
Mail mail2("title2", "description2");
sender<<mail<<mail2;
return 0;
}
title1
description1
title2
description2
Program ended with exit code: 0
class Complex {
public:
Complex(double r = 0, double i = 0):real(r), image(i){}
friend istream & operator>>(istream & ci, Complex & c) {
ci>>c.real;
ci>>c.image;
return ci;
}
friend ostream & operator<<(ostream & co, Complex & c) {
co<<"("<<c.real<<","<<c.image<<")"<<endl;
return co;
}
private:
double real;
double image;
};
int main(int argc, const char * argv[]) {
Complex c, c1;
cin>>c>>c1;
cout<<c<<c1;
return 0;
}
1 2
3 4
(1,2)
(3,4)
Program ended with exit code: 0
custom type conversion
自动类型转换, 其实就是一个单参数构造函数而已, 没有什么神奇的.
class Point3D;
class Point2D {
friend class Point3D;
public:
Point2D(int x = 0, int y = 0):_x(x), _y(y){}
operator Point3D(void);
private:
int _x;
int _y;
};
class Point3D {
friend class Point2D;
public:
Point3D(int x = 0, int y = 0, int z = 0):_x(x), _y(y), _z(z){}
explicit Point3D(const Point2D & d2) {
this->_x = d2._x;
this->_y = d2._y;
this->_z = rand()%100;
}
void dumpFormat() {
cout<<"("<<_x<<","<<_y<<","<<_z<<")"<<endl;
}
private:
int _x;
int _y;
int _z;
};
Point2D::operator Point3D(void) {
return Point3D(this->_x, this->_y, rand()%100);
}
Point3D convert(Point2D d2) {
return Point3D(d2);
}
int main(int argc, const char * argv[]) {
srand((unsigned)time(0));
Point2D d2(10, 100);
Point3D d3 = static_cast<Point3D>(d2);
// Point3D d3 = (Point3D)d2;
// d3 = convert(d2);
d3.dumpFormat();
return 0;
}
functor
仿函数, 看似比较高级的应用, 其本质只不过和运算符从冲裁的本质是调用函数一样.
class Pow {
public:
double operator() (double x, int y) {
int ret = 1;
for (int i = 0; i < y; i++) {
ret *= x;
}
return ret;
}
};
int main(int argc, const char * argv[]) {
int a = 5;
cout<<pow(a, 5)<<endl;
Pow mypow;
mypow(a, 2);
cout<<mypow(a, 5)<<endl;
return 0;
}
bool myCompare(int a, int b) {
return a < b;
}
class Compare {
public:
Compare(bool b = true):flag(b){}
bool operator() (int a, int b) {
if (flag == true) {
return a > b;
} else {
return a < b;
}
}
private:
bool flag;
};
int main(int argc, const char * argv[]) {
int arr[6] = {1, 3, 5, 8, 6, 4};
vector<int> vi(arr, arr + 6);
#if 0
//method1
vector<int>::iterator itr;
for (itr = vi.begin(); itr != vi.end(); ++itr) {
cout<<*itr<<endl;
}
//method2
for (auto itr = vi.begin(); itr != vi.end(); ++itr) {
cout<<*itr<<endl;
}
//method3
for (auto i:vi) {
cout<<i<<endl;
}
#endif
sort(vi.begin(), vi.end(), myCompare);
for (auto i:vi) {
cout<<i<<endl;
}
sort(vi.begin(), vi.end(), Compare(false));
for (auto i:vi) {
cout<<i<<endl;
}
return 0;
}
smart pointer
智能指针, 类似于自动释放池? 出了作用域后自动释放堆内存.
class A {
public:
A() {
cout<<"A()"<<endl;
}
void xxxx() {
cout<<"xxxx"<<endl;
}
~A() {
cout<<"~A()"<<endl;
}
};
class SmartPtr {
public:
SmartPtr(A * pa) {
_pa = pa;
}
A & operator*() {
return *_pa;
}
A * operator->() {
return _pa;
}
~SmartPtr() {
delete _pa;
}
private:
A * _pa;
};
void foo() {
#if 0
A a;
A * p = new A;
delete p;
auto_ptr<A> p(new A);
p->xxxx();
(*p).xxxx();
#endif
SmartPtr sp(new A);
sp->xxxx();
(*sp).xxxx();
}
int main(int argc, const char * argv[]) {
foo();
return 0;
}
A()
xxxx
xxxx
~A()
Program ended with exit code: 0
memory customization
主要用于内存定制, 其实感觉没什么太大的意义, 封装的使用吧..
class A {
public:
A() {
// _x = 100;
// _y = 200;
cout<<"A()"<<endl;
}
void xxxx() {
cout<<_x<<_y<<endl;
}
~A() {
cout<<"~A()"<<endl;
}
void *operator new(size_t size) {
cout<<"operator new"<<endl;
cout<<size<<endl;
void * p = malloc(size);
((A*)p)->_x = 100;
((A*)p)->_y = 200;
cout<<p<<endl;
return p;
}
void operator delete(void * p) {
cout<<"operator delete"<<endl;
cout<<p<<endl;
}
void * operator new[](size_t size) {
cout<<"operator new[]"<<endl;
cout<<size<<endl;
void *p = malloc(size);
cout<<p<<endl;
return p;
}
void operator delete[] (void * p) {
cout<<"operator delete[]"<<endl;
cout<<p<<endl;
free(p);
}
private:
int _x;
int _y;
};
int main(int argc, const char * argv[]) {
#if 0
A * pa = new A;
pa->xxxx();
delete pa;
#endif
A * pa = new A[10];
delete[] pa;
return 0;
}
operator new[]
88
0x10291f740
A()
A()
A()
A()
A()
A()
A()
A()
A()
A()
~A()
~A()
~A()
~A()
~A()
~A()
~A()
~A()
~A()
~A()
operator delete[]
0x10291f740
Program ended with exit code: 0
最后
更多新鲜文章可以关注并Star
, 我们一起学习.
GitHub Repo:coderZsq.github.io
Follow: coderZsq · GitHub