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. CF 1025 D. Recovering BST

    D. Recovering BST http://codeforces.com/contest/1025/problem/D 题意: 给出一个连续上升的序列a,两个点之间有边满足gcd(ai ,aj) ...

  2. 2018.10.17校内模拟赛:T2神光

    题面:pdf 首先排序,二分,然后怎么判定是否可行. 最简单的思路是,dp[i][j][k],到第i个,用了j次红光,k次绿光,前i个点都选上了,是否可行.然后转移就行. 然后考试的时候就想到这了,往 ...

  3. 阿里云Ubuntu 14.04 + Nginx + .net core + MySql

    前段时间帮朋友写了一个网站,现在做一个记录. .Net Core 安装: curl https://packages.microsoft.com/keys/microsoft.asc | gpg -- ...

  4. C#特性的简单介绍

    特性应该我们大多接触过,比喻经常使用的[Obsolete],[Serializable]等下面我就主要介绍一个特性的一些用法 摘自MSDN定义:用以将元数据或声明信息与代码(程序集.类型.方法.属性等 ...

  5. Spring学习(十)-----Spring依赖检查

    在Spring中,可以使用依赖检查功能,以确保所要求的属性可设置或者注入. 依赖检查模式 4个依赖检查支持的模式: none – 没有依赖检查,这是默认的模式. simple – 如果基本类型(int ...

  6. requests,unittest——多接口用例,以及需要先登录再发报的用例

    之前写过最简单的接口测试用例,本次利用unittest进行用例管理,并出测试报告,前两个用例是两个不同网页的get用例,第三个是需要登录才能访问的网页A,并在其基础上访问一个需要在A页面点开链接才能访 ...

  7. Echarts简单图表

    一.实现要点 常用可视化图表库 Echarts HighCharts D3.js neo4j (NOSQL) 1.导入js库 <script type="text/javascript ...

  8. 高可用Kubernetes集群-2. ca证书与秘钥

    四.CA证书与秘钥 kubernetes集群安全访问有两种方式:"基于CA签名的双向数字证书认证"与"基于BASE或TOKEN的简单认证",生产环境推荐使用&q ...

  9. C++数字三角形问题与dp算法

    题目:数字三角形 题目介绍:如图所示的数字三角形,要求从最上方顶点开始一步一步下到最底层,每一步必须下一层,求出所经过的数字的最大和. 输入:第一行值n,代表n行数值:后面的n行数据代表每一行的数字. ...

  10. 第1章 Python基础

    一.安装Python windows: 1.下载安装包     https://www.python.org/downloads/ 2.安装     默认安装路径:C:\python27 3.配置环境 ...