C++中函数是一种类型!C++中函数是一种类型!C++中函数是一种类型!

函数名就是变量!函数名就是变量!函数名就是变量!

(---20160618最新消息,函数名不是变量名。。。囧)

(---20160714最新消息,C++没有函数类型。。。囧)

(---但是,我认为把它们当成类型和变量更容易理解!!!)

重要的事情要说三遍。。。

C++ Primer学习笔记(二)

类的构造函数
与类同名,且无返回类型。
同类的成员函数一样,也可以在类中声明,在类外定义。
格式:
  类名(): 成员1(成员1初始化值), 成员2(成员2初始化值) { }
以上,冒号至大括号中间的部分,称为构造函数的初始化列表,用于调用类成员的构造函数来初始化。
没有在初始化列表中显式指定初始化的成员,将会隐式的初始化。
 
如果没有显式的定义一个构造函数,那编译器会生成一个默认构造函数。
--建议只适用于仅包含类类型成员的类。
默认构造函数不会初始化内置类型成员!
 
 
类的一般使用方式:有类user,则user.h是声明,user.cpp是定义,成员函数通常放入user.cpp中。
 

  1. #include <iostream>
  2. #include <string>
  3.  
  4. using namespace std;
  5.  
  6. //test const
  7. int main(){
  8. //------------测试非引用------------
  9. int no=;
  10. const int no2=no; //OK
  11. int no3=no2; //OK!
  12. //上面得出结论:非引用类型的赋值无所谓const
  13.  
  14. //------------测试引用------------
  15. int &noref=no;
  16. const int &noref1=no;
  17.  
  18. // int &no2ref=no2;
  19. const int &no2ref1=no2;
  20.  
  21. int &no3ref=no3;
  22. const int &no3ref1=no3;
  23. // 上面得出结论:const引用可以指向const及非const。但非const引用只能指向非const。
  24.  
  25. //------------测试指针------------
  26. int *pno=&no;
  27. const int *pno_1=&no;//指向const的指针,可以指向非const
  28.  
  29. // int *pno2=&no2;//指向非const的指针,只能指向非const
  30. const int *pno2_1=&no2;
  31.  
  32. int *pno3=&no3;
  33. const int *pno3_1=&no3;
  34. // 上面得出结论:见备注
  35.  
  36. return ;
  37. }
 
//我擦,有谁能告诉我int怎么转成string吗?例如姓名年龄 一起输出。
 
 
如果两个函数声明的返回类型和形参表完全匹配, 则将第二个函数声明视为第一个的重复声明。如果两个函数的形参表完全相同,但返回类型不同,则第二个声明是错误的。

形参与 const 形参的等价性仅适用于非引用形参。有 const 引用形参的函数与有非 const 引用形参的函数是不同的。类似地,如果函数带有指向 const 类型的指针形参, 则与带有指向相同类型的非 const 对象的指针形参的函数不相同。
注意:函数名也是变量,所以也存在被屏蔽的可能。--函数是一种类型!!!
例如:有个init(),而局部变量int init=0;则会屏蔽掉init()!!!
即:局部变量能屏蔽掉同名函数!!!
同理:局部声明的函数,将屏蔽外部声明的函数。。。屏蔽所有同名的函数,包括重载的。
 
在 C++ 中,名字查找发生在类型检查之前。
仅当形参是引用或指针时,形参是否为 const 才有影响。
可基于函数的引用形参是指向 const 对象还是指向非 const 对象, 实现函数重载。将引用形参定义为 const 来重载函数是合法的,因为编译器可以根据实参是否为 const 确定调用哪一个函数。

重复强调, 编译器可以判断: 如果实参是 const 对象,则调用带有 const* 类型形参的函数;否则,如果实参不是 const 对象, 将调用带有普通指针形参的函数。

但是,不能基于指针本身是否const来实现函数重载!
f(int *);
f(const int *);//redeclaration
因为const的是指针,而非指针所指向的类型。在上述两种情况中, 都复制了指针, 指针本身是否为 const 并没有带来区别。
 
 
函数的指针,是指向函数类型。
像其他指针一样,函数指针也指向某个特定的类型--函数类型。
函数类型由其返回类型以及形参表确定, 而与函数名无关。
例如:bool (*pf) (const string &, const string &); // pf的括号是必须的
这个语句将 pf 声明为指向函数的指针,它所指向的函数带有两个 const string& 类型的形参和 bool 类型的返回值。

可以使用typedef简化函数指针的使用。
  1. typedef bool (*cmpFcn) (const string &, const string &);
上面定义了一个指向函数的指针类型的名字:cmpFcn。
 
 
在引用函数名但又没有调用该函数时,函数名将被自动解释为指向函数的指针。
所以,可以使用函数名对函数指针进行初始化或赋值。
  1. cmpFcn pf1=; //ok
  2. cmpFcn pf2=lengthCompare; //ok
  3. pf1=lengthCompare; //ok
  4. pf2=pf1; //ok
直接引用函数名,等效于在函数名上取地址。
  1. cmpFcn pf1=lengthCompare;
  2. cmpFcn pf2=&lengthCompare;
 
不同类型的函数指针不能转换!!!
 
通过函数指针可以调用函数,而且不需要显式解引用操作!
  1. lengthCompare("hi", "bye"); //直接调用函数
  2. pf("hi", "bye"); //隐式解引用!
  3. (*pf)("hi", "bye"); //显式解引用!
 
函数指针作为形参!卧槽,感觉要进入lambda了!
  1. void func(const string &, const string &, bool(const string &, const string &)); //隐式
  2. void func(const string &, const string &, bool (*)(const string &, const string &)); //显式
 
函数指针作为返回值!卧槽,这绝对是lambda!
  1. int (*ff(int))(int*,int); //QNMD
  2. 其中:ff(int) 是函数,返回 int (*)(int*,int),也就是返回函数指针。
 
  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4.  
  5. int strCmp(const string&, const string&);
  6. int xxx(const string&, const string&);
  7.  
  8. //函数指针
  9. int main(){
  10. string str1="hehe";
  11. string str2="abc";
  12.  
  13. cout<<"strCmp(str1, str2):"<<strCmp(str1, str2)<<endl;
  14.  
  15. //函数指针
  16. int (*ext)(const string&,const string&); //(*strCmp)的括号是必须的。如果声明:int *strCmp(const string&, const string&)
  17.  
  18. typedef int (*fp)(const string&, const string&);//类似声明
  19. fp p0=;
  20. cout<<"p0:"<<p0<<endl;
  21. fp p1=strCmp;
  22. fp p2=p1;
  23. p0=p2;
  24.  
  25. cout<<"p0(\"---\", \"xxxxxxx\")"<<p0("---", "xxxxxxx")<<endl;
  26. cout<<"p1(str2, str1):"<<p1(str2, str1)<<endl; //why?
  27. cout<<"p2(str2, str1):"<<p2(str2, str1)<<endl; //why?
  28.  
  29. fp p3=xxx;
  30. cout<<"p3:"<<p3<<endl;//why 1?
  31. cout<<"p3(\"a\", \"b\"):"<<p3("a", "b")<<endl;
  32.  
  33. ext =xxx;
  34. cout<<"ext:"<<ext<<endl;//why 1?
  35. cout<<"ext(str1, str2):"<<ext(str1, str2)<<endl;
  36.  
  37. //结论:type (*pf)(parameter list)就已经定义了一个函数指针pf。
  38. //typedef可以定义函数指针的类型,而非函数指针。该类型可以定义指针。
  39. //0函数指针输出0;其他则输出1。
  40. //通过函数指针可以直接调用函数:只要后面跟上实参列表即可!函数指针会隐式的解引用--当然也可以显式的解引用!
  41.  
  42. return ;
  43. }
  44.  
  45. int strCmp(const string &str1, const string &str2){
  46. return str1.size()-str2.size();
  47. }
  48.  
  49. int xxx(const string &str1, const string &str2){
  50. return ;
  51. }
 
 
而所谓返回函数指针,或者作为形参,其实都是操作函数指针变量---需要注意,只是返回,不是调用函数!!
而且,建议配合typedef 使用,否则难明白。
例如:
  int (*func(p.l.))(p.l. of fp);  //p.l. = parameter list;   fp=function pointer
可以先定义:typedef  int (*fp)(p.l. of fp);
然后,前面就可以写成:fp func(p.l.);
 
注意:允许将形参定义为函数类型,但函数的返回类型则必须是指向函数的指针,而不能是函数!!!
具有函数类型的形参所对应的实参,将被自动转换为所指向相应函数类型的指针。但是,当返回的是函数时,同样的转换操作无法实现!
  1. typedef int func(p.l);//这里的func是函数类型,不是函数指针!所有int xxx(p.l)形式的函数!
  2. void f1(func); //ok 函数类型可以作为形参
  3. func f2(int); //error 函数类型不能作为返回值!
  4. func *f3(int); //ok 函数类型指针可以作为返回值(其实就是函数指针)
上面的关键是:函数是一种类型!!!函数名是变量!!!

C++ Primer学习笔记(三) C++中函数是一种类型!!!的更多相关文章

  1. Struts2学习笔记(三):result配置的各项视图转发类型

    Struts 1: <action path="/user" type="org.sunny.user.action.UserAction" ...> ...

  2. MySQL学习笔记(三):常用函数

    一:字符串函数 需要注意的几个细节: 1.cancat中有一个字符串为null,则结果为null. 2.left(str,x) 和 right(str,x)中x为null,则不返回任何字符串,不是nu ...

  3. angular学习笔记(三)-视图绑定数据的两种方式

    绑定数据有两种方式: <!DOCTYPE html> <html ng-app> <head> <title>2.2显示文本</title> ...

  4. C++ Primer学习笔记(二)

    题外话:一工作起来就没有大段的时间学习了,如何充分利用碎片时间是个好问题. 接  C++ Primer学习笔记(一)   27.与 vector 类型相比,数组的显著缺陷在于:数组的长度是固定的,无法 ...

  5. Typescript 学习笔记三:函数

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  6. ES6学习笔记<三> 生成器函数与yield

    为什么要把这个内容拿出来单独做一篇学习笔记? 生成器函数比较重要,相对不是很容易理解,单独做一篇笔记详细聊一聊生成器函数. 标题为什么是生成器函数与yield? 生成器函数类似其他服务器端语音中的接口 ...

  7. MYSQL学习笔记三:日期和时间函数

    MYSQL学习笔记三:日期和时间函数 1. 获取当前日期的函数和获取当前时间的函数 /*获取当前日期的函数和获取当前时间的函数.将日期以'YYYY-MM-DD'或者'YYYYMMDD'格式返回 */ ...

  8. [Firefly引擎][学习笔记三][已完结]所需模块封装

    原地址:http://www.9miao.com/question-15-54671.html 学习笔记一传送门学习笔记二传送门 学习笔记三导读:        笔记三主要就是各个模块的封装了,这里贴 ...

  9. 学习笔记(三)--->《Java 8编程官方参考教程(第9版).pdf》:第十章到十二章学习笔记

    回到顶部 注:本文声明事项. 本博文整理者:刘军 本博文出自于: <Java8 编程官方参考教程>一书 声明:1:转载请标注出处.本文不得作为商业活动.若有违本之,则本人不负法律责任.违法 ...

随机推荐

  1. Python atan2() 函数

    描述 atan2() 返回给定的 X 及 Y 坐标值的反正切值. 语法 以下是 atan2() 方法的语法: import math math.atan2(y, x) 注意:atan2()是不能直接访 ...

  2. 从错误中学python(4)——最小公约数与辗转相除法

    题目 给你两个正整数a和b, 输出它们的最大公约数 辗转相除法 辗转相除法的步骤 def gcd(b,a): b,a=a,b%a if a==0: return b else: return gcd( ...

  3. 连接mysql-front数据库出现‘执行错误1251’的解决办法(有效)

    原因是MySQL8.0版本的加密方式和MySQL5.0的不一样,连接会报错. 解决方法:更改加密方式 控制台中先连接mysql: 再输入: ALTER USER 'root'@'localhost' ...

  4. php - 时间操作

    ini_set('date.timezone','Asia/Shanghai'); http://www.w3school.com.cn/php/func_date_strtotime.asp str ...

  5. 使用 powerdesigner 将数据库表结构逆向工程生成对应的word文档

    本机系统win10 + mysql 5.7.17 + powerDesigner 16.5 + mysql-connector-odbc-5.3.9-winx32.msi 1 使用 PowerDesi ...

  6. scrapy 的一个例子

    1.目标: scrapy 是一个爬虫构架,现用一个简单的例子来讲解,scrapy 的使用步骤 2.创建一个scrapy的项目: 创建一个叫firstSpider的项目,命令如下: scrapy sta ...

  7. Centos网络配置小工具

    之前在CentOS 6下编辑网卡,直接使用setup工具就可以了. 但在新版的CentOS 7里,setuptool已经没有网络编辑组件了,取而代之的是NetworkManager Text User ...

  8. ny269 VF

    VF 时间限制:1000 ms  |  内存限制:65535 KB 难度:2   描述 Vasya is the beginning mathematician. He decided to make ...

  9. ny12 喷水装置(二)

    喷水装置(二) 时间限制:3000 ms  |  内存限制:65535 KB 难度:4   描述 有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n(n<=10000)个点状的 ...

  10. Build IKAnalyzer With Solr 5.1.0

    中文分詞裡IKAnalyzer和結巴是大家比較常用的分詞器, 不過IKAnalyzer已經很久沒有更新了, IKAnalyzer中文分词器V2012使用手册也跟IK Analyer 2012-FF H ...