[BoolanC++微专业] Week4笔记

一、conversion function;
一开始想在网上找一找关于conversion function的信息,但是只有在MSDN上找到只言片语:
https://msdn.microsoft.com/en-us/library/5s5sk305.aspx
This content has been relocated. For information about conversion functions, see User-Defined Type Conversions (C++).
好吧巨硬你赢了。
还是从侯捷老师的程序开始讲起吧。

class Fraction
{
public:
    Fraction(int num, int den = 1):m_numerator(num), m_denominator(den) {}
    operator double() const
    {
        return (double) (m_numberator / m_denominator);
    }
private:
    int m_numerator;
    int m_denominator;
}

当程序运行如下时:

Fraction f(3,5);
double d = 4 + f;

如果没有定义

friend Fraction operator+(const double &lhs,const Fraction &rhs)

那么在一般意义上,+号会报错。
但是在类Fraction中有:

operator double() const{}

这个函数,意味着它可以在需要的时候,将类Fraction的实例转double。

从另一个方向来说:

class Fraction
{
public:
    Fraction(int num, int den = 1):m_numerator(num), m_denominator(den) {}
    Fraction operator+(const Fraction &rhs){}
private:
    int m_numerator;
    int m_denominator;
}

此时运行

Fraction d2 = f + 4;

会调用构造函数,将4转化为Fraction(4,1),然后调用Fracion operator+。

然而当Fraction(),operator+,operator double()同时存在时,再次调用就会出现二义性,编译器无法分辨到底应该调用哪一个函数。但是这几个函数都是有必要存在的,怎么办?
此时可以在 Fraction()前加上explicit 修饰词,此时,此构造函数不可以用于隐式地创建Fraction对象。
关键字只对一个实参的构造函数有效,需要多个构造函数不能用于执行隐式转换,所以无需将这些构造函数指定为explicit的。
当我们用explicit关键字声明构造函数时,它将只能以直接初始化的形式使用,而且编译器不会在自动转换中使用该构造函数。

二、智能指针:
智能指针类似于vector,它也是一个模板,让我们创建一个只能指针时,也必须提供额外的信息—-指针指向的类型。默认初始化的智能指针中保存着一个空指针。
由于智能指针只是一个模板类,所以需要重载’*’与’->’来达到与指针相似的用法,

T& operator*() const{}
T& operator->() const {}

关于*运算符的重载,大家应该都没有什么异议,关于->运算符重载大家肯定由疑问。
比如程序如下:

shared_ptr<Foo> sp (new Foo);
sp->method();

此时由于(sp->)method()调用运算符重载,那么不会变成(ptr)methon()这种类型么?
群友在
https://www.ibm.com/support/knowledgecenter/SS2LWA_12.1.0/com.ibm.xlcpp121.bg.doc/language_ref/cplr329.html
找到了解答。

The statement x->f() is interpreted as (x.operator->())->f().

The operator-> is used (often in conjunction with the
pointer-dereference operator) to implement “smart pointers.” These
pointers are objects that behave like normal pointers except they
perform other tasks when you access an object through them, such as
automatic object deletion (either when the pointer is destroyed, or
the pointer is used to point to another object), or reference counting
(counting the number of smart pointers that point to the same object,
then automatically deleting the object when that count reaches zero).

这个是C++中约定俗称的一种语法,这个锅主要还是要甩给’.’运算符无法进行重载,所以给’->’一个特殊的重载形式。

三、迭代器:

An iterator is any object that, pointing to some element in a range of
elements (such as an array or a container), has the ability to iterate
through the elements of that range using a set of operators (with at
least the increment (++) and dereference (*) operators).

The most obvious form of iterator is a pointer: A pointer can point to
elements in an array, and can iterate through them using the increment
operator (++). But other kinds of iterators are possible. For example,
each container type (such as a list) has a specific iterator type
designed to iterate through its elements.

Notice that while a pointer is a form of iterator, not all iterators
have the same functionality of pointers; Depending on the properties
supported by iterators, they are classified into five different

迭代器是一个类,但是它归根究底,还是用指针实现的。比较简单,并没有什么好讲的。

四、仿函数:
其实它的本质就是一个重载了()运算符的类。

// this is a functor
struct add_x {
  add_x(int x) : x(x) {}
  int operator()(int y) const { return x + y; }

private:
  int x;
};

// Now you can use it like this:
add_x add42(42); // create an instance of the functor class
int i = add42(8); // and "call" it
assert(i == 50); // and it added 42 to its argument

std::vector<int> in; // assume this contains a bunch of values)
std::vector<int> out(in.size());
// Pass a functor to std::transform, which calls the functor on every element 
// in the input sequence, and stores the result to the output sequence
std::transform(in.begin(), in.end(), out.begin(), add_x(1)); 
assert(out[i] == in[i] + 1); // for all i

五、模板:
模板是c++泛型编程的基础,一个模板就是创建类或者函数的蓝图或者说公式。
一个函数模板就是一个公式,可以用来生成针对特定类型的函数的版本。

这里写图片描述

类模板同理,但是类模板不能一依靠编译器为类模板推断参数类型,我们必须在模板名后的<>内提供额外信息,用来代替模板参数的实参列表,编译器用这些模板实参来实例化特定的类。

这里写图片描述

模板的参数遵循普通的作用域原则,一个模板参数的名字的可用范围是在其声明之后,至模板参数定义结束之前。在模板内不可以重用模板参数名。
与函数中类似,声明中的模板参数的名字不用与定义中相同。

一个类可以包含本身是模板的成员函数。这种函数称为成员模板。

成员模板不能为虚函数。

为了实例化一个类函数的成员模板,我们必须同时提供类和函数模板的实参。

六、模板模板参数:
主要优点在于:借助于某个依赖于模板参数的类型,就很容易让类模板携带一些状态信息(也就是静态成员变量)。
这里写图片描述

在使用模板模板参数时,需要注意

cCls<string, list> mylist1;

出错的原因在于list模板其实有两个模板参数。
如果想要写成上面这种形式,要不就用using或者typedef将其转化为类型别名,要不就将template<>内的模板参数与实际传入的相匹配。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值