【C++程序设计Ⅱ 兼谈对象模型 ——侯捷大师】心得摘要

1. 转换函数(conversion function)

作用:将类转换为其他类型

class Fraction
{
public:
	...
	operator double() const // 转换函数,格式
	{
		return (double)(m_numerator/m_denominator);
	}
private:
	int m_numerator; //分子
	int m_denominator; // 分母
};

//测试代码:
Fraction f(3, 5);
double d = 4 + f; // 调用 operator double()

编译器的步骤:
首先,寻找operator+的重载,找 int + Fraction的函数,没有找到,编译器尝试失败。
然后再找能否将Fraction 转换为double函数,找到了转换函数,就可以编译成功了。

2. explicit-one-argument-ctor

class Fraction
{
public:
	explicit Fraction(int num, int den = 1):m_numerator(num),m_denominator(den)
	{}
private:
	int m_numerator;
	int m_denominator;
}

Fraction f(3, 5);
Fraction d2 = 4 + f; // error

如果没有explicit,4可能会被转换为fraction,与上面 f 可能转换为double,导致二义性。
关键字explicit一般用在构造函数

3. pointer-like classes(智能指针和迭代器)

智能指针

template<class T>
class shared_ptr
{
public:
	T& operator*() const // *重载
	{
		return *px;
	}
	T& operator->() const // ->重载
	{
		return px;
	}
	...
private:
	T* px;
	long* pn;
	...
}

智能指针类一定包括*操作符和->操作符重载。

->有特殊的行为,得到的东西继续要->作用上去

sp->method();

sp->,操作符重载,得到px,然后->继续作用下去,得到:

px->method();

而对于其他的操作符,则会消耗掉。例如:

*sp;
//通过*重载,转换为
*px;

迭代器

例如 list的迭代器:

reference operator*() const
{
	return (*node).data;
}
pointer operator->() const
{
	return &(operator*());
}

4. function-like classes(仿函数)

()操作符, 被称为function call操作符,函数调用操作符,所以类能够接受()操作符,就可以称为 function-like,这样的对象被称为函数对象

class test
{
public:
	void operator() (const string& str) const 
	{...}
	...

//调用
test func;
func("hello!");
func()("hello!"); // error

和其他的操作符不同,调用()操作符时,需要省略()

5. member template(成员模板)

模板类内,有成员函数是模板函数,被称为成员模板。

标准库大量的类中,一般是构造函数为成员模板,能够让构造函数更有弹性。

template <typename _Tp>
class shared_ptr:public __shared_ptr<_Tp>
{
...
	template<template _Tp1>
	explicit shared_ptr(_Tp1* __p)
		:__shared_ptr<_Tp>(__p) {}
}

// 调用
Base* ptr = new Derived1; // up-cast

6. 模板特化

设计模板后,对某些函数进行局部特征化,编译器会优先考虑特化程序

// 泛化
template <class key>
struct hash{};

//特化
template<>
struct hash<char>
{ ... }

template<>
struct hash<int>
{ ... }

//调用
cout << hash<int>()(1000);

7. 模板偏特化

个数偏特化

模板有多个参数,只特化其中一部分参数,顺序是从左向右。

template<typename T, typename Alloc=....>
class Vector
{ ... };

// 偏特化
template<typename Alloc= ....>
class vector <bool, Alloc>
{ ... };

范围偏特化

进行范围特化,例如特化为指针。

// 程序1
template<typename T> //泛化
class C 
{ ... };

// 程序2
template<typename U> // 范围偏特化
class C<U*>
{ ... };

//调用
C<string> obj1; // 应用程序1 泛化版本
C<string*> obj2; // 应用程序2 范围偏特化版本

8. C++11的三个主题

数量不定的模板参数

把参数分为一个和一个模板参数包(pack)

// 步骤1
void print() // 0个参数
{}
// 步骤2
template<typename T, typename... Types>
void print(const T& firstArg, const Types&... args)
{
	sizeof...(args); //判断模板参数包是几个
	cout << firstArg << endl;
	print(args...);
}

// 调用
print(7.5, "hello", bitset<16>(377), 42);

auto

编译器自动给你推出类型。有时候类型比较复杂,可以使用auto,让编译器推出来。

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);

ranged-base for

for循环遍历

for(decl : coll){...}
//例如
vector<double> vec;
...
for(auto elem: vec){ ... }  //传值
for(auto& elem: vec){ ... } //传引用

在这里插入图片描述
如上图所示,如果传值,for循环会将容器里的元素逐个复制出来,只是只读,不能修改
如果传引用,则会修改容器里的元素

9. reference

reference概念

reference是引用(别名),其底层是指针,也被称为弱化的指针。其更接近const指针

int &rodents = rats;
// 伪装表示如下,const变量必须初始化
int* const pr = &rats; 
//引用 rodent 等价于 *pr

reference必须初始化,一个reference只能指向一个对象。

object和reference的大小相同,地址也相同(这些都是假象,实际上底层代表指针)。

reference用途

通常用在参数类型和返回类型。

double imag(const double& im) { ... }
int imag(const double  im) { ... } //二义性 
// 其中imag(const double  im)被称为函数签名

由于接口一致,因此会被视为same signature,上述会出现二义性。如果是成员函数可以加 const解决

例如:

double imag(const double& im) { ... }
int imag(const double  im)  const { ... } //ok

10. 对象模型(Object Model)关于vptr 、vtbl

继承会把数据和函数的调用权继承下来

有虚函数就会有vptr指针,指向虚表vtbl

virtual table 放的都是函数指针,指向虚函数

C的时代,会直接通过call跳到函数固定地址,然后return,被称为静态绑定。

而通过指针调用虚函数被称为动态绑定,动态绑定的逻辑意义是通过指针找到vptr, 再找到vtbl,然后再找到指向的虚函数。这正是面向对象的关键所在。

//动态绑定路线的代码形式是:
(*(p->vptr)[n])(p);
//或者是
(*p->vptr[n])(p);

符合以下三点,将会动态绑定,也被称为多态

  • 通过指针
  • 向上转型(继承)
  • 调用函数
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值