阅读于侯捷《C++面向对象高级开发》
太细节,没基础不要看,有一些我也看不懂
文章目录
- 阅读于侯捷《C++面向对象高级开发》
- 一、
- 二、三大函数:拷贝构造,拷贝赋值,析构
- 三、堆,栈,内存管理
- 四、类模板、函数模板及其他
- 五、组合与继承
- 六、虚函数与多态
- 七、委托相关设计
- 八、导读
- 1、conversion function 转换函数
- 2、non-explicit-one-argument ctor
- 3、explicit-one-argument ctor
- 4、Pointer-like classes
- 5、function-like classes
- 6、 namespace
- 7 、class template
- 8、function template
- 9、member template
- 10、specialization
- 11、parital specialization
- 12、template template parameter
- 13、C++标准库
- 14、variadic templates、auto、range-base for (C++ 11语法糖)
- 15、Reference
- 16、`Inheritance+Composition` 关系下的构造和析构
- 17、vptr、vtbl
- 18、this
- 19、Dynamic Binding
- 20、const
- 21、Operator new、Operator delete
- 18、this
- 19、Dynamic Binding
- 20、const
- 21、Operator new、Operator delete
一、
complex.h
:
#ifndef __COMPLEX__
#define __COMPLEX__
//防卫式函数声明
calss complex
{
public:
complex(double r=0,double i=0):re(r),im(i){}
complex& operator +=(const complex&);
double real()const {return rm;}
double imag()const {return im;}
private:
double re,im;
friend complex& __doapl(complex* const complex&); //友元函数
}
#endif
complex.cpp
:
inline complex& __doapl(complex* ths,const complex& r) //由于第一个形参要改变,不能加const,第二个不变,可以加const
{
ths->re += r.re;
ths->im +=r.im;
return *ths;
}
inline complex& complex::operator += (const complex& r) //如果return非函数内新建的,不是local,则可以返回引用
{
return __doapl(this,r);
}
inline complex operator + (const complex& x,const complex& y) //只能return 值,不能return reference
{
return complex(real(x)+real(y),imag(X)+imag(y)); //直接类名加初值,相当于新建一个类,在初始化。是一个临时对象
}
#include<iostream.h>
//重载<<操作符
ostream& operator <<(ostream & os,const complex& x) //输出流重载操作符:只能是非成员函数
{
return os<<'('<<real(x)<<','<<imag(x)<<')';
}
pass/return by value 传值
pass/return by reference 传引用
二、三大函数:拷贝构造,拷贝赋值,析构
Class with pointer member 必须有 copy ctor 和 copy op=(拷贝构造,拷贝赋值)
string.h
#ifndef __MYSTRING__
#define __MYSTRING__
class String
{
public:
String(const char* cstr = 0);
String(const String& str); //拷贝构造
String& operator=(const String& str); //拷贝赋值
~String(); //析构
char* get_c_str() const{return m_data;} //不改变值,加const
private:
char* m_data;
}
inline String::String(const char* cstr = 0) //使用举例:String s2("hello");String s1();
{
if(cstr){
m_data = new char[strlen(cstr)+1]; //根据传进来的字符长度+1,创建新内存
strcpy(m_data,cstr);
}
else{ //未指定初值
m_data = new char[1];
*m_data = '\0';
}
}
inline String::String(const String& str){
m_data = new char[strlen(str.m_data)+1];
strcpy(m_data,str.m_data);
}
inline String::operator=(const String& str) //String s1("hello");String s2(s1);s2=s1
{
if(this == &str) //检测自我赋值(self assignment)
return *this;
delete[] m_data; //清空内存
m_data = new char[strlen(str.m_data)+1]; //新建内存
strcpy(m_data,str.m_data); //赋值
return *this;
}
inline String::~String(){
delete[] m_data;
}
#include<iostream.h>
ostream& operator<<(ostream& os,const String str)
{
os<<str.get_c_str();
return os;
}
#endif
String s1("helllo ");
String s2(s1); //等价于 String s2=s1;
三、堆,栈,内存管理
Stack 存在于某作用域(scope)的一块内存空间(自动释放)
Heap 由操作系统提供的一块global内存空间 ,程序可动态分配(需要手动delete)
stack objects生命期:auto object 离开作用域自动释放
static object 其生命在作用域结束之后仍然存在,知道整个程序结束
global object 其生命在整个程序结束之后,才结束。
new char[*] delete[] * array new 搭配 array delete
String* p=new String[3];
delete [] p; //唤起3次dtor(析构函数)
//
delete p; //唤起1次dtor(析构函数) ???
//如果没有指针,delete [] p 和 delete p 一样
四、类模板、函数模板及其他
static data members //多个实例用同一个内存
static member functions //
class Account{
public:
static double m_rate;
static void set_rate(cosnt double& x){m_rate=x;}
};
double Account::m_rate = 8.0;
int main(){
Account::set_rate(5.0);
Account a;
a.set_rate(7.0);
//调用static函数的方法:1、通过object调用;2、通过class name 调用
}
把 ctors
放在private
区
class A{
public:
static A& get Instance(return a;);
setup() { }
private:
A();
A(const A& rhs);
static A a; //没有人使用,a也存在,浪费内存
}
A::getInstance().setup(); //设计模式
//2、
class A{
public:
static A& get Instance();
setup() { }
private:
A();
A(const A& rhs);
}
A& A::getInstance(){ //只有人使用时,a才存在
static A a;
return a;
}
A::getInstance().setup(); //设计模式
类模板
template<typename T>
class complex{
public:
complex(T r=0,T i=0):re(r),im(i){}
T real()const {return rm;}
T imag()const {return im;}
private:
T re,im;
friend complex& __doapl(complex* const complex&); //友元函数
}
int main()
{
complex<double> c1(2.5,1.5);
complex<int> c2(2,6);
}
function template
template <class T>
inline const T& min(const T& a,const T& b){
return b<a ? b:a;
}
stone r1(2,3),r2(3,3),r3;
r3 = min(r1,r2 )
namespace
namespace std
{
//....
}
using dirctive
#include<iostream.h>
using namespace std;
int main(){
cin>>....;
cout<<endl;
}
using declaration
#include<iostream.h>
using std::cout;
int main(){
std::cin>>....;
cout<<std::endl;
}
//or
#include<iostream.h>
int main(){
std::cin>>....;
std::cout<<std::endl;
}
五、组合与继承
Inheritance
继承 is-a
Base //base class 的 析构函数必须是virtual
Derived
//构造由内而外: Derived的构造函数先调用Base的deagult构造函数,然后才执行自己
//析构由外而内: Derived的析构函数先执行自己,然后才调用Base的deagult析构函数
class Derived:public Base{//,,,};
Composition
复合 has-a
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mU77EC9b-1594823376168)(C:\Users\jiame\AppData\Roaming\Typora\typora-user-images\1594443587123.png)]
template <class T>
class queue{
protected:
deque<T> c;
public:
//利用c的操作函数完成
bool empty() const { return c.empty();}
size_type size() const { return c.size();}
//。。。
}
Container<<**>>--->component
Contaniner object{Component part}
//构造由内而外: Container的构造函数先调用Component的deagult构造函数,然后才执行自己
//析构由外而内: Container的析构函数先执行自己,然后才调用Component的deagult析构函数
Delegation
委托 Composition by reference
//file String.hpp
class StringRep;
class String
{
public:
String(const char* cstr = 0);
String(const String& str); //拷贝构造
String& operator=(const String& str); //拷贝赋值
~String(); //析构
char* get_c_str() const{return m_data;} //不改变值,加const
private:
StringRep* rep; //Handle Body
};
//file String.cpp
class StringRep{
friend class String{
//....
};
六、虚函数与多态
virtual
non-virtual
,不希望derived class
重新定义(override
,覆写)它,
virtual
函数,希望derived class
重新定义(override
,覆写)它,而且它已经有默认定义
pure virtual
函数,希望derived class
重新定义(override
,覆写)它,而且它没有默认定义
通过子类的对象调用父类的函数时,若该函数在子类中有override
,则执行子类的函数定义
(Template Method 设计模式之一 )
Inheritance+Composition
关系下的构造和析构
七、委托相关设计
。。。。。。(暂时阵亡)
八、导读
1、conversion function 转换函数
class Fraction
{
public:
Fraction(int num,int den=1):m_numerator(num),m_denominator(den){}
operator double() const{ //返回类型默认double
return (double)m_numerator/(double)m_denominator;
}
private:
int m_numerator;
int m_denominator;
Fraction f(3,5);
double d=4+f //调用operator double()将f转成double类型 :0.6
2、non-explicit-one-argument ctor
class Fraction
{
public:
Fraction(int num,int den=1):m_numerator(num),m_denominator(den){}
Fraction operator +(const Fraction& f) {
return Fraction(....);
}
private:
int m_numerator;
int m_denominator;
Fraction f(3,5);
Fraction d=4+f //调用non-explicit ctor将4转成Fraction,然后调用operator+
3、explicit-one-argument ctor
class Fraction
{
public:
explicit Fraction(int num,int den=1):m_numerator(num),m_denominator(den){}
//若不加explict,下面两个函数有二义性
Fraction operator +(const Fraction& f) {
return Fraction(....);
operator double() const{ //返回类型默认double
return (double)m_numerator/(double)m_denominator;
}
private:
int m_numerator;
int m_denominator;
Fraction f(3,5);
Fraction d=f+4 //
4、Pointer-like classes
关于智能指针
template<class T>
class shared_ptr
{
public:
T& operator*()const{
return *pt;
}
T* operator->()const{
return px;
}
shared_ptr(T* p):px(p){}
private:
T* px;
long* pn;
}
shared_ptr<Foo> sp(new Foo);
Foo (*sp); //指针能用的操作符,这个都能用
sp->method(); //== px->method();
迭代器
5、function-like classes
仿函数
像函数的对象
6、 namespace
namespace jj01
{
}
namespace jj02
{
}
int main(int argc,char** argv)
{
jj01::test();
jj02::test();
return 0;
}
7 、class template
…
8、function template
。。。
9、member template
template <class T1,class T2>
struct pair{
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
pair():first(T1()),second(T2()){}
pair(const T1& a,const T2& b):first(T1),second(T2){}
template<class U1,class U2> //成员又是一个模板(无情套娃)
pair(const pair<U1,U2>& p):first(p.first),second(p.second){}
}
10、specialization
特化 (反义:泛化)
template <class Key> //泛化
struct hash{};
template<>
struct hash<char>{ //特化
size_t operator()(char x) const {return x;}
}
template<>
struct hash<int>{
size_t operator()(int x) const {return x;}
}
template<>
struct hash<long>{
size_t operator()(long x) const {return x;}
}
cout<<hash<long>()(1000);
11、parital specialization
模板偏特化–个数的偏
template<typename T,typename ALloc=...>
class Vector{
...
};
//T-->bool,后面的默认,称之为个数的偏,只能从左到右
template<tpename Alloc=...>
class vector<bool,Alloc>
{
...
};
范围的偏 :比如任意类型 --特化>必须指针类型
template<typename T>
class C{
...
};
template<typename T>
class C<T*>{
...
};
//
C<string> obbj1;
C<string*> obj2;
12、template template parameter
模板模板参数(又套娃???)
template<typename T,template<typename T>class Container>
class XCls{
private:
Container<T> c;
public:
//...
};
//use
template<typename T>
using Lst = list<T,allocator<T>>;
XCls<string,list> mylst1;
XCls<string,Lst> mylst2;
13、C++标准库
STL。。。。
cout<<__cpluscplus<<endl;//查看cpp编译器版本
14、variadic templates、auto、range-base for (C++ 11语法糖)
ariadic templates
数量不定的模板参数pack
template<typename T,typename... Types> //'...'代表不定数量的参数
void print(const T& firstArg,const Types&... args)
{
cout<<firstArg<<endl;//sizeof...(args) 返回 args...一包的参数数量
print(args...); //递归调用,至少有一个参数,另写一个函数兼容,参数依次减少
}
void print(){
}
auto
自动选择返回类型
list<string> c;
....
auto ite = find(c.begin(),c.end(),target);
range-base for
for(int i: {2,3,4,5}){
cout<< i <<endl;
}
vector<double> vec;
....
for(auto elem : vec){ //pass by value
cout<<elem<<endl; //若elem *= 3,不会改变vec中的值
}
for(auto& elem : vec){ //pass by reference
elem *= 3; //因为pass by reference,会改变vec中的值
}
15、Reference
int x=0;
int* p = &x; //p is a poniter to x
int& r = x; //r is a reference to x;r代表x,r,x都是0
int x2 = 5;
//注意:sizeof(r) == sizeof(r), &x == &r object和其reference的大小,地址都相同(假象)
r = x2; // r不能重新代表其他物体,r,x现在都是5;
int& r2 =r; 现在r2 是5(r2 代表 r:亦相当于代表x(又又又套娃??)
double imag(const double& im) {}
double imag(const double im) {}
//"same signature"二者不能同时存在
//“imag(const double im) {}” :signature
16、Inheritance+Composition
关系下的构造和析构
base
|
Derived --> Component
**构造由内而外:**Derived的构造函数先调用Base的deagult构造函数,然后调用Component的default构造函数,然后才执行自己
**析构由外而内:**与构造相反。。
17、vptr、vtbl
虚指针、。。。。。(看不懂)
18、this
略过
19、Dynamic Binding
A<-B<-C
B b;
A a = (A)b;
a.vfuncl(); //静态绑定
A* pa = new B; //动态绑定
pa->vfuncl();
pa = &b;
pa->vfuncl();
20、const
当常成员的const和non-const版本同时存在,
const object 只会调用const版本
non-const object 只会调用non-const版本。
const object non-const object
const member functions Y Y
non-const member functions N Y
21、Operator new、Operator delete
global:
inline Void* operator new(size_t size){
return myAlloc(size);
}
inline void* operator new[](size_t size){
return myAlloc(size);
}
member operator new/delete
此处不详细,另寻他家吧。。。
17、vptr、vtbl
虚指针、。。。。。(看不懂)
18、this
略过
19、Dynamic Binding
A<-B<-C
B b;
A a = (A)b;
a.vfuncl(); //静态绑定
A* pa = new B; //动态绑定
pa->vfuncl();
pa = &b;
pa->vfuncl();
20、const
当常成员的const和non-const版本同时存在,
const object 只会调用const版本
non-const object 只会调用non-const版本。
const object non-const object
const member functions Y Y
non-const member functions N Y
21、Operator new、Operator delete
global:
inline Void* operator new(size_t size){
return myAlloc(size);
}
inline void* operator new[](size_t size){
return myAlloc(size);
}
member operator new/delete
此处不详细,另寻他家吧。。。