C++面向对象高级编程(下)
泛型编程(Generic Programming
)(模板) 和面向对象编程(Object-Oriented Programming
)虽然分属不同思维,但它们正是C++的技术主流;
深入探索面向对象之继承关系(inheritance
)所形成的对象模型(Object Model
),包括隐藏于底层的 this
指针,vptr
(虚指针),vtbl
(虚表),virtual mechanism
(虚机制),以及虚函数(virtual functions
)造成的polymorphism
(多态)效果。
1、转换函数没有返回类型,没有传入参数,后面应该加const
2、类模板 class template,使用的时候要说明类型
template<typename T>
class complex
{
public:
complex( T r = 0,T i = 0): re (r), im (i){ }
comp1ex& operator+=(const complex&);
T real () const { return re; }
T imag () const { return im; }
private:
T re,im ;
friend complex& _doapl (complex* , const complex&);
};
使用:
{
complex<double>c1(2.5,1.5);
complex<int> c2(2,6);
...
}
3、函数模板function template,使用的时候不需要说明类型,编译器会对function template进行实参推导。
class stone
{
public:
stone(int w,int h, int we): _w ( w ),_h (h), _weight (we){}
bool operator<(const stone& rhs) const { return _weight < rhs._weight; }
private:
int _w, _h,_weight;
};
template <class T>
inline
const T& min (const T&a, const r& b)
{
return b < a ? b : a ;
}
使用:
stone r1(2,3), r2(3,3), r3;
r3 = min(r1, r2);
4、成员模板 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(a) , second(b) { }
template <class U1, class U2>
pair (const pair<U1, U2>& p)
: first(p.first) , second(p.second) { } //把初值的头尾放进来,放入本身的头尾
//把子类赋给对应的父类,up-cast
};
5、specialization,模板特化
template <class Key>//泛化
struct hash { };
//特化
template<>
struct hash<char> {
size_t operator () (char x) const { return x; }
};
template<>
struct hash<char> {
size_t operator () (int x) const { return x; }
};
template<>
struct hash<char> {
size_t operator () (long x) const { return x; }
};
6、template template parameter,模板模板参数
template<typename T, template <typename T>
class Container//容器
>
class xCls
{
private:
Container<T> c ;
public:
...
} ;
template<typename T>
using Lst = list<T,allocator<T>>;
使用:
xCls<string, list> mylst1; //错误
xc1s<string, Lst> mylst2; //正确
7、variadic templates (since C++11) 数量不定的模板参数
void print()//没有参数的时候调用这个
{
}
template<typename T, typename... Types>// ...表示一包
void print(const T& firstArg, const Types&... args)
{
cout << firstArg << endl;
print(args...);//一直调用本身,直到没有参数,调用上面的print()
}
想要知道后面的一包有多少个,可以使用 sizeof...(args)
…就是一个所谓的
pack
(包)
用于 template parameters,就是template parameterspack
(模板参数包)
用于function parameter types,就是function parameter typespack
(函数参数类型包)
用于function parameters,就是function parameterspack
(函数参数包)
8、智能指针 auto
(since C++11)
list<string>c;
...
list<string>::iterator ite ;
ite = find(c.begin(), c.end(), target);
可以写成:
list<string>c;
...
auto ite = find(c.begin(), c.end(), target);//赋值的时候,auto 会自动推出类型
//声明变量的时候不能使用auto, 推不出来类型
9、ranged-base for (since C++11)
例如:
for (int i : {2, 3, 5, 7, 9, 13, 17, 19}){
cout<< i << endl;
}
vector<double> vec;
...
for ( auto elem : vec ) {//pass by value
cout <<elem <<endl;
}
for ( auto& elem : vec ) {//pass by reference
elem *= 3;
}
10、reference
int x = 0;
int* p = &x;
int& r = x; //r代表(别名)x,现在r,x都是0
int x2 = 5;
r = x2; // (❌错误),r不能重新代表其他变量,相当于是x的一个别名。现在 r,x 都是5
int& r2 = r; //现在r2是5 (r2代表r,亦相当于代表×)
注意∶object 和 reference 的大小相同,地址也相同(全是假象!)
1、sizeof( r) = sizeof(x)
2、&x = &r ;
Java里面所有的变量都是reference
reference
通常不用于声明变量,而用于参数类型(parameter type)和返回类型(return type)的描述。
以下被视为 “same signature”(所以二者不能同时存在):
11、函数继承的调用权,不是继承他的内存的大小。
12、vptr
虚指针和 vtbl
虚表
动态绑定必须满足三个条件,(而静态绑定一定调用到某个地址。),实现 多态:
- 必须是用指针来调用,如上面的
p
指针; - 这个指针是向上转型的(祖先);
- 调用的是虚函数。
每种形状的图形都有自己的虚函数 draw()
13、this
指针,动态绑定