[侯捷C++面向对象高级开发] 学习笔记上

1.头文件与类声明
-----------------Complex.h-------------------
template <typename T>
class Complex
{
     
public:
	Complex(T r = 0,T i = 0) //带默认实参的构造函数,r,i默认为0
	:re(r),im(i)
	{
     }
	Complex& operator+=(const Complex&);
	double real() const {
     return re;} //inline函数
private:
	T re,im;
	
	friend Complex& __doapl(Complex* const Complex&);
};
--------------------Complex.cpp----------------
{
     
	Complex<double> c1(2.5,1.7);//构造函数
}

inline函数
	在类中声明并且定义,则该函数即为inline函数,但是是否为inline还是
	取决于编译器本身,如果不在类中,需要设计成inline需要explict声明;

2.构造函数

 Complex C1(2,1);
 Complex C2; //
 Complex* p = new Complex(4);
 
 不带指针的类多半不需要写析构函数;
 函数重载;
 
class A{
     
public:
	static A& getInstance();	//Singleton模式
	setup();
private:
	A();
	A(const A& rhs);
	...
 };
 A& A::getInstance()
 {
     
	static A a;
	return a;
 }
 
==> A::getInstance().setup();

在函数体,如果不改变数据内容的,可以在函数体后加const;

参数传递:传参和传引用
良好的习惯:最好什么都能传引用,这样传参效率更高,因为只传了一个int*指针;
			返回值类型也尽量返回引用;
template <typename T>
class Complex
{
     
public:
	Complex(T r = 0,T i = 0) 
	:re(r),im(i)
	{
     }
	Complex& operator+=(const Complex&);
	double real() const {
     return re;} 
	double imag() const (return im;)
private:
	T re,im;
	
	friend Complex& __doapl(Complex* ,const Complex&);
};
ostream& operator << (ostream& os, const ostream& x)
{
     
	return os << '(' <<real(x)<<','<<imag(x)<<')';
}
// 自由取得friend的private成员变量
inline Complex& __doapl (Complex* ths,const Complex& r)
{
     
	ths->re += r.re;
	ths->im += r.im;
	return *ths;
}
//相同class的各个object互为friend(友元)
class complex 
{
     
public:
	complex(double r = 0,double i = 0 )
	:re(r),im(i)
	{
     }
	int func(const complex& param)
	{
     
		return param.re + param.im;
	}
private:
	double re,im;
}

{
     
	complex c1(2,1);
	complex c2;
	c2.func(c1); //C2可以使用C1的private参数,这种现象可以用相同class的各个object互为friend(友元)解释;
}

/*****
*	class body外的各种定义
*	什么情况下可以pass by reference
*   什么情况下不可以pass by reference
*/ 
inline complex&
__doapl(complex* ths,const complex& r)
{
     
	ths->re += r.re;
	ths->im += r.im;
	return *ths;
}
inline complex7
complex::operator+=(const complex& r)
{
     
	return __doapl(this,r);
}
5.操作符重载与临时对象
/*
*	传递者无需知道接受是以reference形式接受
*/
inline complex&
__doapl(complex* ths,const complex& r)
{
     
	ths->re += r.re;
	ths->im += r.im;
	return *ths;  // return了一个value,但是不影响
}
inline complex&
complex::operator+=(const complex& r)
{
     
	return __doapl(this,r);
}

{
     
	complex c1(2,1);
	complex c2;
	c2 += c1; // C2=>this,C1=>r ;;this指针
}
/*
*	全局函数:::没带class名
*/
inline double real(const complex& x)
{
     
	return x.real();
}

{
     
complex c1(2,1);
cout<< real(c1);

/*
*	operator overloading (操作符重载-2 非成员函数)
*	下面函数不可以使用reference返回,因为他们返回的
*	 必定是个local object
*
*	temp object(临时对象) ===>> typename();
*   出了函数体后临时对象就被析构了
*/
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,const complex& y)
{
     
	return complex(real(x) + y,imag(x));
}
inline complex operator+(const complex& x,const complex& y)
{
     
	return complex(x + real(y),imag(y)); ///产生个临时对象
}

------------------------------------------------------------
/*
*	操作符重载不要写成成员函数形式,而是写成全局函数的形式;
*	
*/
inline complex operator+(const complex& x)
{
     
	return x;
}
inline complex operator-(const complex& x)
{
     
	return complex(-real(x),-imag(x));
}
{
     
	complex c1(2,1);
	complex c2;
	cout<< -c1; //这里的+和-代表的是正号和负号
	cout<< +c2;
}
/*
*	为了让<<可以连续传参,需要将ostream作为返回类型 
*/
#include 
ostream& operator<<(ostream& os,const complex& x)
{
     
	return os << '(' <<real(x)<<',' <<imag(x)<<',';
}

{
     
	complex c1(2,1);
	cout<<conj(c1);
	cout<<c1<<conj(c1);
}

7.三大函数:构造拷贝、拷贝复制、析构
class String
{
     
public:
	String(const char* cstr = 0);
	String(const String& str); //拷贝构造
	String& operator=(const String& str); //拷贝复制
	~String();
	(inline)char* get_c_char() 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::String(const String& str)
{
     
	/*防止自我赋值*/
	if(this == &str)
	{
     
		return *this;
	}
	delete[] m_data;
	m_data = new char[strlen(str.m_data) + 1];
	strcpy(m_data,str.m_data);  //深拷贝
	return *this;
}

8.堆、栈与内存管理
Stack :存在于某作用域的一块内存空间,例如当你调用函数时,函数本身即会形成一个stack用来放置它接收的参数
		以及返回地址;
	在函数体内声明的任何变量,其所使用的内存块都取自上述的stack;
Heap: 或者称为system heap,是指由操作系统提供的一块global内存空间,程序可能由分配(dynamic allocated)从中
		获得若干区块;
		
class Complex{
     ...};
...
{
     
	Complex c1(1,2); ==>stack
	Complex *p = new Complex(3); ==> heap ,需要手动delete
}

stack objects的生命期:在上述c1便是stack object,其生命在作用域结束之际,被主动析构掉
但是静态对象其生命周期在程序结束时才结束;
{
     
	static Complex c2(1,2);
}
global object的生命周期与static对象一样,在程序结束时才被释放;



new :先分配内存,再调用拷贝赋值
Complex* pc = new Complex(1,2);
		||
		||
		\/
(1)void* mem = operator new (sizeof(Complex));
(2)pc = static_cast<Complex*> (mem);
(3)pc->Complex::Complex(1,2);==>Complex::Complex(this,1,2)

delete pc;
		||
		||
		\/
(1)String::~String(ps); //先调用析构函数
(2)operator delete(ps); //再释放内存   ==>内部调用free()


10.类模板、函数模板及其他

class A{
     
public:
	static A& getInstance(){
     return a;}
	setup(){
     ...}
private:
	A();
	A(const A& rhs);
	static A a; //对象已存在
}
==>A::getInstance().setup();

class A{
     
public:
	static A& getInstance();
	setup(){
     ...}
private:
	A();
	A(const A& rhs);
}
==> A& A::getInstance(){
     static A a; return a;} ///只有调用getInstance()才会产生对象


cout可以接受不同类型参数的原因:
cout是继承ostream的类;
class _IO_ostream_withassign : public ostream{
     
	...
};
extern _IO_ostream_withassign

class ostream : virtual public ios{
     
public:
	ostream& operator<<(char c);
	ostream& operator<<(unsigned char c);
	ostream& operator<<(signed har c);
	ostream& operator<<(const unsigned char* c);
	ostream& operator<<(int c);
	ostream& operator<<(long c);
	...
};
/*
*	类模板
*/
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;}
private:
	T re,im;
};
{
     
	complex<double>c1(1.1,2,2);
	complex<int> c2(2,3);
}
/*
*	函数模板
*/
template <class T>
inline const T& min(const T& a,const T& b)
{
     
	return b < a ? b : a;
}
/*
*	namespace
*   在工程中,如果加入自己的代码,可以使用特定的名字空间
*	这样就不会发生混乱;
*/
namespace std{
     
	...
}

11.组合与继承

1.Composition(符合)

2.Delegation(委托)
/*
*	Handle/Body
*/

class StringRep;
class String{
     
public:
	String();
	String(const String&);
	String& operator=(String& rhs);
private:
	StringRep *rep; //===>通过指针将两个类相连,但是生命周期有可能不一致
};

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

3.Inheritance
如果一个类将来会成为父类,则将析构函数设置成virtual12.虚函数与多态

non-virtual函数:你不希望derived class 重新定义(override)virtual函数:你希望derived class 重新定义,并且你对她已经有默认定义

pure virtual函数:你希望derived class 一定需要重写,你对她没有默认定义

class Shape{
     
public:
	virtual void draw()const = 0;
	virtual void error(const std::string& msg);
	int objectID()const;
};
class Rectangle:public Shape{
     ...};
class Ellipse:public Shape{
     ...};


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

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

13.委托相关

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