《c++必知必会》学习心得——day2

来源:互联网 发布:三菱编程软件安装方法 编辑:程序博客网 时间:2024/06/06 03:22

条款 17 处理函数和数组声明

 

指向函数的指针声明也指向数组的指针声明容易混淆,原因在于函数和数组修饰符的优先级比指针修饰符的优先级高,所以通常要圆括号

 

int *f1();   一个返回值为int的函数

int (*fp1)();  一个指针,指向一个返回值为int的函数

 

const int N=12;

int *a1[N]; 一个具有N个int*元素数的数组

int(*ap1)[n]; 一个指针,指向有N个int元素的数组

 

条款 18  函数对象

函数对象就是常规的类对象,但是可以采用逼标准的函数语法来调用它的operator()成员;

就是一个类,但是它用起来就像一个函数一样
在很多 STL 的调用和其它模板库的调用中,这是一个经常会被用到的手段

class Op<class T> {
public:
    bool operator()(const T& lhs, const T& rhs) {
        return lhs < rhs;
    }
};

int a = 1, b = 2
if(comparer(a, b)) {
    printf("%d is less than %d/n", a, b);
}

条款 19 commnd模式和好莱坞法则

 

回调是个一个常见的编程技术,传统上实现为一个指向函数的的简单指针

 

但是这样的函数需要一些数据才能工作但一个函数指针没有相关数据

 

所以我们用函数对象代替函数指针

 

条款 22 Template Method

 

在一个方法中定义一个算法的框架,并将该算法的某些步骤,延迟到子类实现。Template Method使得子类可以重新定义一个算法中的某些特定的步骤,而无需改变整个算法的结构。

“Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.” - GoF

 

换言之,Template Method提供一个方法,以允许子类重写该方法的一部分,而无需重写整个子类。

 

比如,对于某一项任务,如果它有一个复杂的成员函数,并且该成员函数可以分成几个步骤,同时这几个步骤构成成员函数的整体结构式稳定的,但各个子步骤却有很多改变的需求,这样的情形下就特别适合使用Template MethodTemplate Method设计模式就是在确定稳定的成员函数组成结构的前提下,应对各个子步骤的变化。

 

基类决定函数的整体流程,客户通过基类的接口来调用start,派生类的设计者不知道原子操作的何时调用,但他们知道当两个原子操作调用时他们要干什么。因材我们基类金额派生类同心打造了一个完整的函数实现。

 

 

条款 24 成员函数的查找

 

一般分为三步

1编译器查找函数的名字

2从候选者选择最佳匹配函数

3检查是不是有访问函数的权限

 

在c++中 内层作用域名字会隐藏外层作用域中相同的名字

在java中内层作用云中的方法名字和外层是重载的关系

 

条款 25 实参相依的查找

 

这个该项背后的思想很简单,当查找一个函数调用表达式中函数名字时,编译器也会到“包含函数调用实参的类型”的名字空间中检查

adl(argument depending look)在不同输出类型的<<输出时帮我们打理好了一切

 

条款 26 操作符函数查找

也就是退化的adl

 

 

条款 27 能力查询

 

在大多数情况下,类的能力在其接口上已经被明确定义。但是在继承层次上,底层的派生类很可能继承多个基类。

 

在某种情况下,我们不知道一个对象是否具有所需的能力。这时,我们被迫执行一个能力查询,C++中,能力查询通常是通过对“不相关”的类型进行dynamic_cast转换而表达的。 

这种dynamic_cast 用法通常被称为“横向转型”,它试图在一个类层次结构中执行横向转换,而不是向上或者向下转换。 

 

如果一个对象没有继承于该类,那么dynamic_cast将会失败,返回空指针,否则就是转型成功。 

能力查询只是偶尔需要,但往往会被过度使用,它们通常是糟糕设计的“指示器”,因此最好避免对一个对象的能力进行运行期能力查询。 

 

shape *s =getsomeshape();

 

if(Rollable *roller=daynamic_cast<Rollable *>(s))

 

roller->roll();

 

条款 28 指针比较的含义

 

在c++中一个对象可以有多个指针,因此,指针比较不是关于地址的比较,而是关于对象统一性的问题

 

有继承关系的两个指针可以用==来比较

 

条款 29  虚构造函数与prototype

条款 30  factory method模式

条款 31 协变返回参数

 

以上三章貌似十分看不懂

 

条款 32 禁止复制

 

可以通过将其复制操作声明为private 同时不为之提供定义来不接受对象的复制

 

class Nocopy{

public:

         Nocopy(int);

        //...

private:

         Nocopy(const Nocopy &);

         Nocopy &operator =( const Nocopy &);

};

 

void aFunc{Nocopy};

void otheraFunc{const Nocopy};

Nocopy a(12);//right

Nocopy b(a);//wrong  调用复制构造函数

Nocopy c=12;//wrong  隐式调用复制构造函数

a=b;//wrong  调用复制构造函数

aFunc(a);//wrong  传值 调用复制构造函数

aFunc(12);//wrong  隐式调用复制构造函数

otherFunc(a);//right

otherFunc(12);//right

 

何时使用复制构造函数:按值传递对象,函数返回对象,用一个对象初始化另一个对象即复制初始化时,根据元素初始化列表初始化数组元素。这四种情况都将调用复制构造函数。记住,复制构造函数只能用于初始化,不能用于赋值,赋值时不会调用复制构造函数,而是使用赋值操作符。

 

条款 33制造抽象基类

 

抽象基类通常用于表示目标问题领域的抽象概念,创建这种类型的对象时没有什么意义的,我们通过至少声明一个纯虚函数使得一个基类成为抽象的,编译器将会确保无人能够创建该抽象基类的任何对象

 

 

 

原创粉丝点击