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. 成都Uber优步司机奖励政策(4月18日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  2. 苏州Uber优步司机奖励政策(4月11日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  3. 请求头(request headers)和响应头(response headers)解析

    *****************请求头(request headers)***************** POST /user/signin HTTP/1.1    --请求方式 文件名 http ...

  4. 【LG4841】城市规划

    [LG4841]城市规划 题面 洛谷 题解 记\(t_i\)表示\(i\)个点的无向图个数,显然\(t_i=2^{C_i^2}\). 设\(f_i\)表示\(i\)个点的无向连通图个数,容斥一下,枚举 ...

  5. directive 指令一

    什么是Directive Directive将一段html,js封装在一起,形成一个可以复用的独立个体,具有特定的功能.angularjs中的指令通常是比较小的组件,它相当于是给我们提供了一些公共的自 ...

  6. mac php版本切换

    mac os 中自带php版本,但是很多扩展是不带的. 这个网站: http://php-osx.liip.ch/提供了几乎所有的php版本 通过输入 curl -s http://php-osx.l ...

  7. 「日常训练」Jongmah(Codeforces-1110D)

    题意 你有n个数字,范围[1, m],你可以选择其中的三个数字构成一个三元组,但是这三个数字必须是连续的或者相同的,每个数字只能用一次,问这n个数字最多构成多少个三元组? 分析 根据官方Editori ...

  8. Charles连接苹果及JSON乱码情况解决

    1.  Charles的JSON乱码情况解决: 点击Charles界面上的help—SSL proxying—install Charles Root Certificate,将证书安装到[受信任的根 ...

  9. and_or_not 逻辑运算符的操作注解!

    python操作:

  10. webgl 包围盒子

    包围盒子是鼠标选择物体的一种实现方式,当从相机出发,经过鼠标点形成的射线和物体的包围盒子相交时,就代表物体被选中