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

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

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

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

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

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

C++ Primer学习笔记(二)

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

#include <iostream>
#include <string> using namespace std; //test const
int main(){
//------------测试非引用------------
int no=;
const int no2=no; //OK
int no3=no2; //OK!
//上面得出结论:非引用类型的赋值无所谓const //------------测试引用------------
int &noref=no;
const int &noref1=no; // int &no2ref=no2;
const int &no2ref1=no2; int &no3ref=no3;
const int &no3ref1=no3;
// 上面得出结论:const引用可以指向const及非const。但非const引用只能指向非const。 //------------测试指针------------
int *pno=&no;
const int *pno_1=&no;//指向const的指针,可以指向非const // int *pno2=&no2;//指向非const的指针,只能指向非const
const int *pno2_1=&no2; int *pno3=&no3;
const int *pno3_1=&no3;
// 上面得出结论:见备注 return ;
}
 
//我擦,有谁能告诉我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简化函数指针的使用。
typedef bool (*cmpFcn) (const string &, const string &);
上面定义了一个指向函数的指针类型的名字:cmpFcn。
 
 
在引用函数名但又没有调用该函数时,函数名将被自动解释为指向函数的指针。
所以,可以使用函数名对函数指针进行初始化或赋值。
cmpFcn pf1=;    //ok
cmpFcn pf2=lengthCompare; //ok
pf1=lengthCompare; //ok
pf2=pf1; //ok
直接引用函数名,等效于在函数名上取地址。
cmpFcn pf1=lengthCompare;
cmpFcn pf2=&lengthCompare;
 
不同类型的函数指针不能转换!!!
 
通过函数指针可以调用函数,而且不需要显式解引用操作!
lengthCompare("hi", "bye"); //直接调用函数
pf("hi", "bye"); //隐式解引用!
(*pf)("hi", "bye"); //显式解引用!
 
函数指针作为形参!卧槽,感觉要进入lambda了!
void func(const string &, const string &, bool(const string &, const string &)); //隐式
void func(const string &, const string &, bool (*)(const string &, const string &)); //显式
 
函数指针作为返回值!卧槽,这绝对是lambda!
int (*ff(int))(int*,int); //QNMD
其中:ff(int) 是函数,返回 int (*)(int*,int),也就是返回函数指针。
 
#include <iostream>
#include <string>
using namespace std; int strCmp(const string&, const string&);
int xxx(const string&, const string&); //函数指针
int main(){
string str1="hehe";
string str2="abc"; cout<<"strCmp(str1, str2):"<<strCmp(str1, str2)<<endl; //函数指针
int (*ext)(const string&,const string&); //(*strCmp)的括号是必须的。如果声明:int *strCmp(const string&, const string&) typedef int (*fp)(const string&, const string&);//类似声明
fp p0=;
cout<<"p0:"<<p0<<endl;
fp p1=strCmp;
fp p2=p1;
p0=p2; cout<<"p0(\"---\", \"xxxxxxx\")"<<p0("---", "xxxxxxx")<<endl;
cout<<"p1(str2, str1):"<<p1(str2, str1)<<endl; //why?
cout<<"p2(str2, str1):"<<p2(str2, str1)<<endl; //why? fp p3=xxx;
cout<<"p3:"<<p3<<endl;//why 1?
cout<<"p3(\"a\", \"b\"):"<<p3("a", "b")<<endl; ext =xxx;
cout<<"ext:"<<ext<<endl;//why 1?
cout<<"ext(str1, str2):"<<ext(str1, str2)<<endl; //结论:type (*pf)(parameter list)就已经定义了一个函数指针pf。
//typedef可以定义函数指针的类型,而非函数指针。该类型可以定义指针。
//0函数指针输出0;其他则输出1。
//通过函数指针可以直接调用函数:只要后面跟上实参列表即可!函数指针会隐式的解引用--当然也可以显式的解引用! return ;
} int strCmp(const string &str1, const string &str2){
return str1.size()-str2.size();
} int xxx(const string &str1, const string &str2){
return ;
}
 
 
而所谓返回函数指针,或者作为形参,其实都是操作函数指针变量---需要注意,只是返回,不是调用函数!!
而且,建议配合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.);
 
注意:允许将形参定义为函数类型,但函数的返回类型则必须是指向函数的指针,而不能是函数!!!
具有函数类型的形参所对应的实参,将被自动转换为所指向相应函数类型的指针。但是,当返回的是函数时,同样的转换操作无法实现!
typedef int func(p.l);//这里的func是函数类型,不是函数指针!所有int xxx(p.l)形式的函数!
void f1(func); //ok 函数类型可以作为形参
func f2(int); //error 函数类型不能作为返回值!
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. Kali 2.0最新国内源:阿里云,中科大

    版权声明:本文为博主原创文章,转载请注明来源. https://blog.csdn.net/liushulin183/article/details/51519628  刚刚要给kali装个中文输入法 ...

  2. 软件测试自动化之- API Test

    API测试 从本质上来说,API测试是用来验证组成软件的那些单个方法的正确性,而不是测试整个系统本身. API测试也被称为单元测试(Unit Testing), 模块测试(Module Testing ...

  3. node 服务器开发必备神器 —— nodemon

    nodemon 官方网站:http://nodemon.io/ github地址:https://github.com/remy/nodemon/ 简介:Nodemon 是一款非常实用的工具,用来监控 ...

  4. How to install Mysql in the CentOS

    This article will walk through you the process of installing and updating latest MySQL 5.7.9 version ...

  5. Gcc\MingW\Cygwin\Msys简介

    一.GCC的历史GCC是一个原本用于Unix-like系统下编程的编译器.不过,现在GCC也有了许多Win32下的移植版本.所以,也许对于许多Windows开发者来说,GCC还是一个比较陌生的东西.所 ...

  6. XILINX之RAM使用指南(加个人总结)

    先加点自己的总结:真双口RAM可以在任意时间访问任意地址,两个端口的地址是一样的,即共享内存和地址.这就会带来一个问题:同时读写一个地址会发生冲突.基于这个点矛盾就要设置限制条件,这个在Xilinx ...

  7. 【Android】3.0 第3章 百度地图及其应用--预备知识

    分类:C#.Android.VS2015.百度地图应用: 创建日期:2016-02-04 一.概述 这一章先来点有意思的百度地图应用示例,然后再分章详细介绍用C#开发Android App的各种基本技 ...

  8. 使用Eclipse创建的第一个javabean,cannot resolved to a type

    第一个原因是我没有把eclipse编译好的class文件放在项目的build文件夹中的(我创建的是dynamic web project),你要把/build/classes/文件夹给合并到WebCo ...

  9. JAVA-JSP之include指令

    相关资料:<21天学通Java Web开发> 结果总结:1.包含的可以是一个HTML文件,也可以是一个文件文件,当然也可以是一个JSP文件.2.只有当被包含的文件执行完成后,JSP文件才会 ...

  10. python学习笔记(15)--pygame的安装

    说明: 1. 现在是2017.3.9号,最新的python版本是3.6,最新的pygame是1.9.3,这两个最好都用32位的. 2. pygame1.9.3下载地址:http://www.lfd.u ...