class 与类:
class分为两种,一种带指针,一种不带指针,不带指针的一般不需要有构析函数,带指针的需要.
参数传递与返回值:
设计模式::Singleton(单例构造,外界仅允许用一份):
class A{
public:
static A& getInstance(); // 注意static
setup (){...}
private:
A();
A(const A& rhs);
...
}
A& A::getInstance(){
static A a; // 注意static
return a;
}
main:
A::getInstance().setup();
参数传递与返回值:
函数后加const,如:
double real () const {return re;} 不会改变数据内容加const
参数传递与返回值:
如果对象加const,而函数没有加const,则该函数不能调用
博客园https://home.cnblogs.com/u/DSkite/
参数传递与返回值:
参数传递尽量不要传值(pass by value),要传引用(pass by reference(to const))
引用在底部是一个指针,参数是压入栈中的,速度比较快.如果传的是const reference 则不可更改
例:
ostrream& operator << (ostream& os ,const complex &x){
return os << '(' << real(x) << ','
<< imag(x) << ')';
}
要传值的情况,在函数内部传输的时候,如果新建了一个对象,如果要把此对象传出,则
参数传递与返回值:
inline与宏差不多,是直接替换;
参数传递与返回值:
相同class的各个object(方法或者变量)互为friends(友元)
操作符重载与临时对象
保守声明(防卫声明)
#ifndef __COMPLEX__
#define __COMPLEX__
...
#endif
操作符重载与临时对象
所有的成员函数都存在 this,this是指向 引用该函数的对象的 指针
例:
inline complex& complex::operator +=(const complex& r){
return __doapl(this,r);
}
inline complex& __doapl(complex* ths,const complex& r){
ths->re += r.re;
ths->im += r.im;
return ths;
}
操作符重载与临时对象
返回值无需注意变量接受是否是以reference(引用)形式接受
操作符重载与临时对象
temp object(临时对象) typename()
下面这个函数不可以 return by reference,,他返回的必定是个local object
inline complex operator- (const complex& x, const complex& y) {
return complex (real(x) + real(y), imag(x) + imag(y));
}
main:
complex c1(2,1);
cout << -c1;
三大函数:拷贝构造,拷贝复制,析构
带指针的
分三步走:
1.删除自己
2.新空间
3.赋值
如
inline String& String::operator=(const String& str)
{
if(this == &str) // 检测自我赋值
return *this;
delete[] m_data; // 1
m_data = new char[ strlen( str.m_data) + 1]; // 2
strcpy(m_data, str.m_data); // 3
return *this;
}
三大函数:拷贝构造,拷贝复制,析构
浅拷贝:
编译器按位拷贝(指针)
深拷贝:
需自己写
三大函数:拷贝构造,拷贝复制,析构
Big three
1.拷贝构造
2.拷贝赋值
3.析构函数
三大函数:拷贝构造,拷贝复制,析构
操作符重载一般都是 全局函数
如果是成员函数,那么cout将会在右边,难以接受;
堆 heap,栈 Stack,与内存管理
Stack,存在某个作用域的一个内存空间,如调用函数,函数会用一个stack放置接收参数和返回地址;
heap, system heap,操作系统提供的一个global空间,程序动态分配其中的若干块block
如{
Complex c1(1,2); // 在stack,离开作用域后自动析构
Complex* p = new Complex(3); // 在heap,需要手动析构
static Complex c2(1,2); // 在作用域后(scope)依然存在,直到程序结束
}
堆 heap,栈 Stack,与内存管理
Complex* pc = new Complex(1,2);
new()编译器转化为
void* men = operator new( sizeof(Complex));//分配内存,其中 operator new是一个函数,内部调用malloc(n)
pc = static_cast<Complex*>(men); // 转型
pc->Complex::Complex(1,2); // 构造函数
堆 heap,栈 Stack,与内存管理
delete pc;
delete 编译器转化为
String::~String(pc); // 析构函数
operator delete(pc); // 释放内存,内部调用free(ps)
堆 heap,栈 Stack,与内存管理
在用new 的时候 ,vc一般是16的倍数,不足补0
debugging
如
Complex* pc = new Complex(1,2);
00000011 Cookie (4h) Cookie 指标记,最后一位 1 则被发出,0则被回收
Debugger Header (32h)
Complex object (8h)
补零
00000011 Cookie (4h)
8 + 32 + 4 + 4*2 ->52 --> 16
非debugging
00000011 Cookie (4h) Cookie 指标记,最后一位 1 则被发出,0则被回收
Complex object (8h)
00000011 Cookie (4h)
4 + 8 + 4 = 16
再如String
非debugg
00000011 Cookie (4h)
String Object (point)(4h)
00000000 (4h)
00000011 Cookie (4h)
4 + 4 + 4 + 4 = 16
堆 heap,栈 Stack,与内存管理
array new 要搭配 array delete
如
Complex *p = new Complex[3];
debugging
51h (4h)
Debugger Header (20h)
array number 3 (4h)
data (3*2*4 = 18h)
no man land (4h)
00000000 (4 * 2h)
51h (4h)
4 + 32 + 24 + 4 +8 +4-> 72 -->80
非debugging
51h (4h)
array number 3 (4h)
data (3*2*4 = 24h)
00000000 (4 * 2h)
51h (4h)
8*3 + 4*2 + 4->36 -->48
如果array new 不搭配 arrary delete
那么只会使用一次构析函数,剩余部分没有构析,然后再删除全部
扩展补充:类模板,函数模板,及其他
如果用了static,那么this 指针就不会再传进来,因为static是共有的
static函数只能处理静态数据
静态数据要定义
扩展补充:类模板,函数模板,及其他
设计模式: Meyers Singleton
class A{
public:
static A& getInstance();
setup(){...}
private:
A();
A(const A& rhs);
...
};
A& A::getInstance(){
static A a;
return a;
}
mian:
A::getInstance().setup();
只有有人调用才出现
而Singleton 是没有人调用都依然存在;
operator type() const; // 隐式转换
explicit complex(...):initialization list{} //explicit 阻止隐式转换
组合与继承
Composition 组合 has-a
如
template <class T,class Sequence = deque<T> >
class queue{
...
博客园https://home.cnblogs.com/u/DSkite/
...
protected:
Sequence c; //底层容器
public:
// 全部操作用 c 的函数操作
bool empty() const{ return c.empt}
};
内存大小是 adapter 大
构造是由内到外
析构是由外到内
Delegation 委托
Compostion by reference
也叫编译防火墙??
例子
class StringRep; // Body
class String{ // Hadnle
public:
BIG THREE
...
private: StringRep* rep; // pimpl
}
包含但是没有完全包含,等需要在用时调用
可以分离实现和接口
也可以共享一个接口
a rep-> n -> Hello|reference count 1
b rep-> n -> Hello|reference count 2
c rep-> n -> Hello|reference count 3
Inheritance 继承 is-a
构造是由内到外
析构是由外到内
基类的析构函数必须时virtual,否则会出现未定义行为 (undefined behavior)
虚函数与多态
Inheritance(继承) with virtual function
non-virtual:你不希望derived class 重新定义|重写(override)
int objectID()const;
virtual: 希望derived class重新定义,且已经有默认定义
virtual void error(const std::string& msg);
pure virtual:希望derived class一定重新定义,且没有默认定义
virtual void draw() const = 0; 博客园https://home.cnblogs.com/u/DSkite/
委托相关设计
23个设计模式
Adapter
Handle/Body pImpI
Template Method
Observer
Composite
Prototype <<Design Patterns Explained Simply>>