0.目录

1.函数对象

2.重载赋值操作符

3.string类

4.小结

1.函数对象

编写一个函数:

  • 函数可以获取斐波那契数列每项的值
  • 每调用一次返回一个值
  • 函数可根据需要重复使用

实现功能:

#include <iostream>
#include <string> using namespace std; int fib()
{
static int a0 = 0;
static int a1 = 1; int ret = a1; a1 = a0 + a1;
a0 = ret; return ret;
} int main()
{
for(int i=0; i<10; i++)
{
cout << fib() << endl;
} cout << endl; for(int i=0; i<5; i++)
{
cout << fib() << endl;
} return 0;
}

运行结果为:

[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out
1
1
2
3
5
8
13
21
34
55 89
144
233
377
610

存在的问题——函数一旦开始调用就无法重来:

  • 静态局部变量处于函数内部,外界无法改变
  • 函数为全局函数,是唯一的,无法多次独立使用
  • 无法指定某个具体的数列项作为初始值

函数对象:

  • 使用具体的类对象取代函数
  • 该类的对象具备函数调用的行为三个字
  • 构造函数指定具体数列项的起始位置
  • 多个对象相互独立的求解数列项

函数调用操作符(( )):

只能通过类的成员函数重载

可以定义不同参数的多个重载函数

最终解决方案——把类的对象当作函数使用:

#include <iostream>
#include <string> using namespace std; class Fib
{
int a0;
int a1;
public:
Fib()
{
a0 = 0;
a1 = 1;
} Fib(int n)
{
a0 = 0;
a1 = 1; for(int i=2; i<=n; i++)
{
int t = a1; a1 = a0 + a1;
a0 = t;
}
} int operator () ()
{
int ret = a1; a1 = a0 + a1;
a0 = ret; return ret;
}
}; int main()
{
Fib fib; for(int i=0; i<10; i++)
{
cout << fib() << endl;
} cout << endl; for(int i=0; i<5; i++)
{
cout << fib() << endl;
} cout << endl; Fib fib2(10); for(int i=0; i<5; i++)
{
cout << fib2() << endl;
} return 0;
}

运行结果为:

[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out
1
1
2
3
5
8
13
21
34
55 89
144
233
377
610 55
89
144
233
377

2.重载赋值操作符

什么时候需要重载赋值操作符?编译器是否提供默认的赋值操作?

  • 编译器为每个类默认重载了赋值操作符
  • 默认的赋值操作符仅完成浅拷贝
  • 当需要进行深拷贝时必须重载赋值操作符
  • 赋值操作符拷贝构造函数有相同的存在意义

示例:

#include <iostream>
#include <string> using namespace std; class Test
{
int* m_pointer;
public:
Test()
{
m_pointer = NULL;
}
Test(int i)
{
m_pointer = new int(i);
}
Test(const Test& obj)
{
m_pointer = new int(*obj.m_pointer);
}
Test& operator = (const Test& obj)
{
if( this != &obj )
{
delete m_pointer;
m_pointer = new int(*obj.m_pointer);
} return *this;
}
void print()
{
cout << "m_pointer = " << hex << m_pointer << endl;
}
~Test()
{
delete m_pointer;
}
}; int main()
{
Test t1 = 1;
Test t2; t2 = t1; t1.print();
t2.print(); return 0;
}

运行结果为:

[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out
m_pointer = 0x252f010
m_pointer = 0x252f030

(在C语言中支持自赋值,于是C++为了兼容C语言,也得支持自赋值。于是在重载赋值操作符的时候,也得处理自赋值的情况。)

问题分析:

一般性原则:

重载赋值操作符,必然需要实现深拷贝!!!

编译器默认提供的函数:

3.string类

下面的代码输出什么?为什么?

示例:

#include <iostream>
#include <string> using namespace std; int main()
{
string s = "12345";
const char* p = s.c_str(); cout << p << endl; s.append("abced"); // p 成为了野指针 cout << p << endl; return 0;
}

运行结果为:

[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out
12345
12345

问题分析:

下面的程序输出什么?为什么?

示例:

#include <iostream>
#include <string> using namespace std; int main()
{
const char* p = "12345";
string s = ""; s.reserve(10); // 不要使用 C 语言中的方式操作 C++ 中的字符串
for(int i=0; i<5; i++)
{
s[i] = p[i];
} cout << s << endl; for(int i=0; i<5; i++)
{
cout << s[i] << endl;
} return 0;
}

运行结果为空:

[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out 1
2
3
4
5

问题分析:

改进后:

#include <iostream>
#include <string> using namespace std; int main()
{
const char* p = "12345";
string s = ""; s = p; cout << s << endl; return 0;
}

运行结果为:

[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out
12345

4.小结

  • 函数调用操作符(( ))是可重载的
  • 函数调用操作符只能通过类的成员函数重载
  • 函数调用操作符可以定义不同参数的多个重载函数
  • 函数对象用于在工程中取代函数指针
  • 在需要进行深拷贝的时候必须重载赋值操作符
  • 赋值操作符和拷贝构造函数有同等重要的意义
  • string类通过一个数据空间保存字符数据
  • string类通过一个成员变量保存当前字符串的长度
  • C++开发时尽量避开C语言中惯用的编程思想

C++解析(19):函数对象、关于赋值和string的疑问的更多相关文章

  1. 不可或缺 Windows Native (19) - C++: 对象的动态创建和释放, 对象的赋值和复制, 静态属性和静态函数, 类模板

    [源码下载] 不可或缺 Windows Native (19) - C++: 对象的动态创建和释放, 对象的赋值和复制, 静态属性和静态函数, 类模板 作者:webabcd 介绍不可或缺 Window ...

  2. (63)Wangdao.com第十天_预处理、预解析_函数 上下文对象、参数列表对象

    预解析.预处理 1. 在全局代码执行之前,js 引擎 就会创建一个栈来存储管理所有的 执行上下文对象 2. 在 全局执行上下文 window 确定以后,进行压栈 3. 在 函数执行上下文对象 确定以后 ...

  3. C++ 数组操作符重载、函数对象分析、赋值操作符

    string类型访问单个字符 #include <iostream> #include <string> #include <sstream> using name ...

  4. 你不知道的JavaScript--Item6 var预解析与函数声明提升(hoist )

    1.var 变量预编译 JavaScript 的语法和 C .Java.C# 类似,统称为 C 类语法.有过 C 或 Java 编程经验的同学应该对"先声明.后使用"的规则很熟悉, ...

  5. python 学习笔记3(循环方式;list初始化;循环对象/生成器/表推导;函数对象;异常处理)

    ### Python的强大很大一部分原因在于,它提供有很多已经写好的,可以现成用的对象 16. 循环方式笔记: 1)range(0, 8, 2)   #(上限,下限,步长)  可以实现对元素或者下标的 ...

  6. python之三元表达式,列表|字典推导式,函数对象

    #### 三元表达式: 就是if....else...的语法糖 # -- 1) 只能解决if...else...结构,其他if分支结构都不管 # -- 2)一个分支提供一个结果: 如果一个分支提供了多 ...

  7. Atitit dsl对于数组的处理以及main函数的参数赋值

    Atitit dsl对于数组的处理以及main函数的参数赋值 1.1. 词法解析..添加了[] 方括号的解析支持1 1.2. Ast建立.添加了数组参数的支持..使用了递归下降法..getparam ...

  8. Python进阶07 函数对象

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 秉承着一切皆对象的理念,我们再次回头来看函数(function).函数也是一个对象 ...

  9. python 函数对象(函数式编程 lambda、map、filter、reduce)、闭包(closure)

    1.函数对象 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 秉承着一切皆对象的理念,我们再次回头来看函数(function).函 ...

随机推荐

  1. pgpool-II的master-slave模式的分析

    磨砺技术珠矶,践行数据之道,追求卓越价值 回到上一级页面: PostgreSQL集群方案相关索引页     回到顶级页面:PostgreSQL索引页 现象描述: 客户来邮件,问:为何Pgpool-II ...

  2. 深度学习:参数(parameters)和超参数(hyperparameters)

    1. 参数(parameters)/模型参数 由模型通过学习得到的变量,比如权重和偏置 2. 超参数(hyperparameters)/算法参数 根据经验进行设定,影响到权重和偏置的大小,比如迭代次数 ...

  3. LAUNCHXL-28379D入门学习-第一篇

    1. 首先安装controlSUITE或者C2000ware软件,TI官网下载,安装后包括C2000的函数库和例程之类的,还可以和CCS搭配使用.controlSUITE安装完之后大约4个G,所以我安 ...

  4. 解决Extjs有IE下z-index属性的问题

    在用Extjs时,有时候,在Google浏览器上面没有任何问题,但是相同的页面在IE下面就会有问题,直接报错,点击中断,进行后可以看到如下的信息: Google里面没这个问题,加一句代码就能解决在窗体 ...

  5. [css 揭秘] :CSS揭秘 技巧(五):条纹背景

    条纹背景 https://github.com/FannieGirl/ifannie/问题:条纹背景 在设觉设计中无处不在,我们真的可以用css 创建图案吗? 这一章相对还是比较复杂的哦!一起get. ...

  6. kobject和kset的一些学习心得

    #include <linux/module.h> #include <linux/kernel.h> #include <linux/kobject.h> #in ...

  7. 【SpringCloud】第十一篇: 断路器监控(Hystrix Dashboard)

    前言: 必需学会SpringBoot基础知识 简介: spring cloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理.服务发现.断路器.路由.微代理.事件总线.全局锁.决策竞选. ...

  8. 四、Django之模型与管理后台-Part 2

    一.数据库安装 打开mysite/settings.py配置文件,这是整个Django项目的设置中心.Django默认使用SQLite数据库,因为Python源生支持SQLite数据库,所以你无须安装 ...

  9. 在Unity中使用带碰撞体的TiledMap

    虽然最近Unity2018版本推出了自己的瓦片地图,但是这个瓦片地图有点BUG,在场景内把瓦片地图铺好做成预制体,动态生成的时候居然丢失了碰撞体,于是我决定还是使用Tiled软件绘制地图并使用Tile ...

  10. 套接口socket编程(Client/Server编程实例)

    基本概念 套接口也就是网络中的ID.网络通信,归根到底还是进程间通信(不同计算机上的进程间的通信).在网络中,每一个节点(计算机或路由器)都有一个网络地址,也就是IP地址. IP地址:在网络中唯一标识 ...