1  原生bool类型

c++里面的bool类型才是真正原生的true和faul,比如常见的大写的“BOOL”,它就不是原生的。

原生的与非原生的bool,它们的区别:

详细说下原生bool与非原生bool之间的差别:

_Bool 这个是c98之后加上的bool类型,和我们原生bool等同。

C++中,建议一直使用原生bool,它是最安全的类型。

补充一点:宏定义一个int类型的bool,之所以这么做,是因为0是false,1是true,在C++中,这种比对是有风险的,可以说是不正确的。


2 头文件的三种标准

在vs2015上默认建立一个项目,VS2015帮我们生成4个文件:

stdafx.h这个是微软给我们的一个大坑。

有可能会导致一个问题:预编译头会导致平台不兼容。

文件后缀cpp和c,编译器会选择不同的编译方式编译。

在以DomainOperatorDemo这个解决方案命名的工程中,生成的DomainOperatorDemo.cpp,有程序员直接改名为main.cpp。告诉别人main方法在这里。

在stdafx.h中,默认包含了3个头文件。我们可以直接在main函数中使用printf()。

其中还包含了tchar.h,这是微软给我们的一个坑,它是windows特定的头文件,它前面有个t,带有很强的平台特性。不要过于依赖这个头文件。

以c++中,stdio.h和cstdio功能一样。

3 补充预编译头:提问stdafx.cpp具体的作用是什么呢?

  可以理解为微软的VC特有的文件,实际上我们可以完全的没有它,直接创建空项目。是给编译器用的,并不是我们所需要的。预编译头,想是给我们一定的便利,但并没有什么卵用。


4  域运算符  

它的作用主要就是来解决一件事:

看示例:

变量不是最终的本质,本质是内存里的表述数据。

作用域访问符::

变量的覆盖原则:就近访问。谁最近,我就去找它。

命名空间与作用域:

  在C语言中,我们了解到,变量的生命周期和作用域,就是看这个变量放在哪,外部的、全局的、局部的,局部的局部的等,在C中对变量的作用域控制力是很弱的。

  所以在C++中,特意加入了一个权限概念:命名空间,加强了作用域的控制。除了全局空间,栈空间,又多了一个自已定义的命名空间。

当域作用符前面为空的时候,表示为全局空间,域作用符前面有名称的,就是命名空间

std是个什么样子的命名空间?看图:

如何自定义一个命名空间:

自定义命名空间除了解决变量重定义的问题,它还有其它的作用吗?答案是有的:工业编程里面,大的项目是很多程序员合作的结果,当另一个伙伴想要访问你一个同名的变量时,命名空间就能很好的分隔区分它们。


5  new&delete    运算符

  前面讲到了全局,讲到了栈,现在说说“堆”:

c中我们学到2个操作函数是 malloc()  和  free()。C++中间添加了new 和 delete ;

#include <iostream>

int main()
{
int *pNum = new int();
std::cout << *pNum; return ;
}

运行:100

在C语言中maloc()一定和free()对应使用,那么C++中也是:new一定对应delete使用。

#include <iostream>

int main()
{
int *pNum = new int();
std::cout << *pNum;
delete pNum;
return ;
}

运行:100

再看:如果new一个数组呢,怎么释放?

#include <iostream>

int main()
{
int *pNum = new int();
std::cout << *pNum; int *pArray = new int[]; delete pNum;
delete[] pArray;
return ;
}

运行:100

注意:new  和  delete  是运算符,它们不是函数。重要的说三遍!老师就在课堂里强调了三次。


 6 什么条件下能够构成重载

看代码,我们在C中是这么写函数的:

#include <cstdio>

void MyCoutInt(int num)
{
printf("%d", num);
} void MyCoutChar(char c)
{
printf("%c",c);
} void MyCoutFloat(float f)
{
printf("%f",f);
} void MyCoutString(char *str)
{
printf("%s", str);
} int main()
{ return ;
}

以上在C中,各个函数因为参数不同,而函数名也要不同,不然就重定义了。C++中,可以这样子写:

#include <cstdio>

void MyCout(int num)
{
printf("%d", num);
} void MyCout(char c)
{
printf("%c",c);
} void MyCout(float f)
{
printf("%f",f);
} void MyCout(char *str)
{
printf("%s", str);
} int main()
{ return ;
}

以C++方式编译:通过~!没有问题!    以前C中是完全不能够的,因为函数名重复了。

改成C方式编译:

#include <stdio.h>

void MyCout(int num)
{
printf("%d", num);
} void MyCout(char c)
{
printf("%c",c);
} void MyCout(float f)
{
printf("%f",f);
} void MyCout(char *str)
{
printf("%s", str);
} int main()
{ return ;
}

编译:

1>------ 已启动生成: 项目: OverloadeDemo, 配置: Debug Win32 ------
1> main.c
1>e:\c_code\overloadedemo\overloadedemo\main.c(9): error C2084: 函数“void MyCout(int)”已有主体
1> e:\c_code\overloadedemo\overloadedemo\main.c(3): note: 参见“MyCout”的前一个定义
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========

改回C++模式,编译就通过,这个例子引入C++的一个机制:重载

重载——允许函数名相同,但后面的参数一定是不同的。如果函数名相同,参数也相同,就不能构成重载:

#include <cstdio>

void MyCout(int num)
{
printf("%d", num);
} void MyCout(int num)
{
printf("%d", num);
} void MyCout(char c)
{
printf("%c",c);
} void MyCout(float f)
{
printf("%f",f);
} void MyCout(char *str)
{
printf("%s", str);
} int main()
{ return ;
}

编译:

1>------ 已启动生成: 项目: OverloadeDemo, 配置: Debug Win32 ------
1> main.cpp
1>e:\c_code\overloadedemo\overloadedemo\main.cpp(9): error C2084: 函数“void MyCout(int)”已有主体
1> e:\c_code\overloadedemo\overloadedemo\main.cpp(3): note: 参见“MyCout”的前一个定义
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========

讲了半天,重载会有什么好处?

#include <cstdio>

void MyCout(int num)
{
printf("%d", num);
} void MyCout(char c)
{
printf("%c",c);
} void MyCout(float f)
{
printf("%f",f);
} void MyCout(char *str)
{
printf("%s", str);
} int main()
{
int num = ;
char c = 'a';
char *str = "I Love Mark";
float f = 1.0002;
MyCout(f);
MyCout(str);
MyCout(num); return ;
}

下断点,运行:

1.000200I Love Mark100

看下C++中cout里面运算符的重载:

再看重载的具体原理,它具体的原理是什么;它里面有些什么潜规则呢?
下个断点,看看重载函数调用的顺序:

看跳转到哪:

其实本质上,C++最终还是生成了4个函数,表面上函数名一样,其本内里是不一样的4个函数。在调用这个函数的时候,编译器会帮我们选择一一对应的函数。根据函数的参数去匹配。

用反汇编查看调用匹配:

充分说明了,内里是不同的,不是表面上看到的一样的。

为什么编译器能给我们一一对应匹配呢?

因为编译器根据符号表里函数名,参数类型,域空间,等元素的不同来重定向函数名:

我们可以假设内里重载的函数名会改名:函数名@类型@类@命名空间……比如:?GetArryLens@MyString@@QAEIXZ

c++里面增加针对函数重载的“命名重定向”与“命名粉碎”的说法:你实际存在符号表里的函数名,被加了参数类型等附加名。这里就有一个问题:

名称被重定向了,命名粉碎了,内里名称已经被更改了,这时当别人调用这个函数的时候,名称已经不是这个我们命名名称了,这里如果别人想要你真实的函数名,会很困扰,这时应该怎么办?这个时候可以加一个前缀extern c :可以使用extern"c"(c编译模式)阻止命名粉碎。

在C中,没有命名粉碎这一概念的。

上面重载都讲参数类型的不同,同名函数重载,那如果这个函数的返回值不同,会不会影响重载失败呢?

重载与否跟返回值没关系,只与函数名和参数有关系:

看测试代码 :

#include <cstdio>

void MyCout(int num)
{
printf("%d\n", num);
} void MyCout(char c)
{
printf("%c\n",c);
} void MyCout(float f)
{
printf("%f\n",f);
}
//MyCout@char* //假设按命名重定向,命名为MyCout@char*
void MyCout(char *str)
{
printf("%s\n", str);
}
//MyCout@char*   //这里也是一样,生成和上面同名了。     
int MyCout(char *str)
{
printf("%s\n", str);
return ;
} int main()
{
int num = ;
char c = 'a';
char *str = "I Love Mark";
float f = 1.0002;
MyCout(f);
MyCout(str);
MyCout(num); return ;
}

编译:报错!

1>------ 已启动生成: 项目: OverloadeDemo, 配置: Debug Win32 ------
1> main.cpp
1>e:\c_code\overloadedemo\overloadedemo\main.cpp(24): error C2556: “int MyCout(char *)”: 重载函数与“void MyCout(char *)”只是在返回类型上不同
1> e:\c_code\overloadedemo\overloadedemo\main.cpp(18): note: 参见“MyCout”的声明
1>e:\c_code\overloadedemo\overloadedemo\main.cpp(23): error C2371: “MyCout”: 重定义;不同的基类型
1> e:\c_code\overloadedemo\overloadedemo\main.cpp(18): note: 参见“MyCout”的声明
1>e:\c_code\overloadedemo\overloadedemo\main.cpp(34): warning C4305: “初始化”: 从“double”到“float”截断
1>e:\c_code\overloadedemo\overloadedemo\main.cpp(36): error C2264: “MyCout”: 函数定义或声明中有错误;未调用函数
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========

命名重定向时,不考虑返回值,关键是参数的类型,参数的多少。重定向没有重名就能重载。

#include <cstdio>

void MyCout(int num)
{
printf("%d\n", num);
} void MyCout(char c)
{
printf("%c\n",c);
} void MyCout(float f)
{
printf("%f\n",f);
}
//MyCout@char*
void MyCout(char *str)
{
printf("%s\n", str);
}
//MyCout@char*@int
int MyCout(char *str,int num)
{
printf("%s\n", str);
return ;
} int main()
{
int num = ;
char c = 'a';
char *str = "I Love Mark";
float f = 1.0002;
MyCout(f);
MyCout(str);
MyCout(num); return ;
}

编译通过。

只要最终命名粉碎后,没有重命名,则能构成重载。

PoEdu - C++阶段班- Lesson02_C to C++的更多相关文章

  1. PoEdu - C++阶段班【Po学校】- Lesson03-4_构造函数&赋值函数&拷贝构造函数&学习方式 - 第6天

    PoEdu - C++阶段班[Po学校]- 第6天 课堂选择题目: 1  关于转换构造函数  ClassDemo demo = 1;  调用转换构造函数 2  关于拷贝赋值函数  demo =2; 首 ...

  2. PoEdu - C++阶段班【Po学校】- Lesson02_类与对象_第4天

    复习:上节作业讲解 注意点: 设计SetString()的时候,要注意重置原来的空间. char * SetString(const char *str) { _len = strlen(str); ...

  3. PoEdu - C++阶段班【Po学校】- 第3天

    引用 C中指针的功能强大,使用起来繁杂,因为指针要控制的东西太多:有指针的类型,指针的解引用,指针空间内的值,它本身是有空间的,有自己的地址等.指针也是强大的,比如:我们要在函数之内,修改方法之外的值 ...

  4. PoEdu - C++阶段班- Lesson07 To Lesson10_C to C++

    07  重载导致的二义性 问题:为什么一定要重载呢?重载能方便我们注重函数的功能,当参数类型不确定时,我们能很便捷的利用重载的机制达到目的. 重载注意点:二义性 看代码: #include <c ...

  5. PoEdu - C++阶段班【Po学校】- 第1课

    1 C++开讲 C ++  伟大的编程语言:能提高程序运行效率,节约更多的资源,"正确的使用C++,能够抑制全球变暖问题". 2 C++能力雷达图 通过 1效率 2灵活度 3 抽象 ...

  6. PoEdu- C++阶段班【Po学校】-Lesson03_构造函数精讲 - 第5天

    复习构造函数:1  与类同名   2  没有返回值   3  自动生成    4  手动后,不会自动生成    5  不在特定的情况下,不会私有  新建 类   两种方法示范   其一:在vs中选择类 ...

  7. PoEduo - C++阶段班【Po学校】-Lesson03-5_运算符重载- 第7天

    PoEduo - Lesson03-5_运算符重载- 第7天 复习前面的知识点 空类会自动生成哪些默认函数 6个默认函数    1  构造  2  析构   3  赋值  4 拷贝构造  5 oper ...

  8. [福大软工] Z班 团队Beta阶段成绩汇总

    Beta敏捷冲刺得分 队伍名 1 2 3 4 5 总分 Dipper 10 10 10 10 10 50 SWSD 9 9 9 9 7 43 五成胜算 10 10 10 10 10 50 人月神教 0 ...

  9. 福州大学软件工程1816 | W班 团队Alpha阶段成绩汇总排名(第9、10次作业)

    写在前面 汇总成绩排名链接 1.作业链接 第九次作业--项目Alpha冲刺(团队) 第十次作业--事后诸葛亮(团队) 2.评分准则 本次作业包括现场Alpha答辩评分(映射总分为100分)+博客分(总 ...

随机推荐

  1. 【uTenux实验】时间管理(系统时间/周期性处理/警报处理)

    1.系统时间管理 系统时间管理函数用来对系统时间进行操作,是OS的一个基础性的东西.个人认为,设置系统时间和获取系统时间对OS来说基本是可有可无的. uTenux提供了三个系统时间相关API.分别用于 ...

  2. ZooKeeper程序员指南(转)

    译自http://zookeeper.apache.org/doc/trunk/zookeeperProgrammers.html 1 简介 本文是为想要创建使用ZooKeeper协调服务优势的分布式 ...

  3. Spark RDD类源码阅读

    每天进步一点点~开搞~ abstract class RDD[T: ClassTag]( //@transient 注解表示将字段标记为瞬态的 @transient private var _sc: ...

  4. centos7编译安装pure-ftpd-1.0.42

    一.下载 wget https://download.pureftpd.org/pub/pure-ftpd/releases/pure-ftpd-1.0.42.tar.gz 二.安装 tar xvf ...

  5. ubuntu下安装php memcache扩展

    memcached 安装sudo apt-get install memcached memcached 参数说明memcached -d -m 50 -p 11211 -u root-m 指定使用多 ...

  6. ASP.NET中进行消息处理(MSMQ) 三(转)

    在本文的前两篇文章里对MSMQ的相关知识点进行了介绍,很多阅读过这前两篇文章的朋友都曾问到过这样一些问题:  1.如何把MSMQ应用到实际的项目中去呢?  2.可不可以介绍一个实际的应用实例?  3. ...

  7. 2015年第六届蓝桥杯C/C++程序设计本科B组决赛

    1.积分之谜(枚举) 2.完美正方形 3.关联账户(并查集) 4.密文搜索 5.居民集会 6.模型染色 1.积分之迷 小明开了个网上商店,卖风铃.共有3个品牌:A,B,C.为了促销,每件商品都会返固定 ...

  8. 62. Divide Two Integers

    Divide Two Integers Divide two integers without using multiplication, division and mod operator. 思路: ...

  9. Linux字符界面下用户账户的设置

    在Linux系统字符界面下创建.修改以及删除用户账户主要使用useradd,usermod和userdel这3个命令. 一.创建用户账户 创建用户账户就是在系统中创建一个新账户,然后为新账户分配用户U ...

  10. C#的 is 和 as 类型转换

    C#在操作类型转换时,提供了 as 和 is , 显式,隐式类型转换,由于显式和隐式类型转换比较容易理解,这里主要介绍下 is 和 as 的转换. 1. is  转换   is 操作符指定一个对象类型 ...