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 <iostream>
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
如果一个类将来会成为父类,则将析构函数设置成virtual;
12.虚函数与多态
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++面向对象高级开发] 学习笔记上
最新推荐文章于 2024-05-21 10:12:11 发布