C过度到C++ (2)
接上一篇博文为什么要有重载
它可以让我们很方便的进行一系列调用
它解决了因为数据类型不同而引发的一些编写代码方面的问题比如, 代码复用问题
比如, 大量代码重复仅仅因为参数类型不同问题.
重载的匹配
// 重载例子
#include <cstdio>
void HadesCout(int num)
{
printf("%d", num);
}
void HadesCout(char* szStr)
{
printf("%s", szStr);
}
void HadesCout(char c)
{
printf("%c", c);
}
void HadesCout(double dNum)
{
printf("%f", dNum);
}
int main()
{
HadesCout("Hello C++\n");
HadesCout(100);
HadesCout(10.0);
HadesCout('H');
return 0;
}我们以例子来看当我们执行
long i = 100; HadesCout(i);语句
我们没有long参数的重载方法, 那么程序会调用谁?
会调用 int 参数的方法
我们加上一个
long参数的方法, 如下:
void HadesCout(long num)
{
printf("%ld", num);
}当我们执行
short i = 100; HadesCout(i);语句
我们没有short参数的重载方法, 那么程序会调用谁?
会调用 int 参数的方法
当我们执行
unsigned long i = 100; HadesCout(i);语句
我们没有unsigned long参数的重载方法, 那么程序会调用谁?
会编译不通过.
为什么会这样?在重载的实现过程中, 会有一个
匹配的过程.
匹配的时候是有规则的.
发生错误是因为它并没有一个匹配的规则.
匹配规则类别: - 精准匹配
提升匹配
- char 可提升至 int
- float 可提升至 double
- ......
类型转换匹配
- int 可转换为 unsigned int
- ......
- 当匹配的规则冲突时(有多个匹配), 就会出现二义性.
建议- 尽量使用精准匹配
- 尽量不要在重载中使用基本数据类型指针来进行重载
重载的二义性
// 举个例子
#include <iostream>
using namespace std;
void f1(long lVal) {}
void f1(char cVal) {}
void f1(char* pcVal) {}
void f1(int* piVal) {}
int main()
{
int iNum = 100;
// 猜猜结果?
f1(iNum);
f2(iNum);
}// 两句话都会报错
// 因为首先, f1没有精准匹配结果
如何解决?
新增精准匹配
类型转换后进行匹配
默认实参(Default Argume)
#include <cstdio>
void HadesCout(int iNum, bool isPrintCrLf = true)
{
printf("%d", iNum);
if (isPrintCrLf)
printf("\n");
}
void HadesCout(char cVal, bool isPrintCrLf = true)
{
printf("%c", cVal);
if (isPrintCrLf)
printf("\n");
}
void HadesCout(char* szVal, bool isPrintCrLf)
{
printf("%s", szVal);
if (isPrintCrLf)
printf("\n");
}
int main()
{
HadesCout(100);
HadesCout("Hello Hades", true);
HadesCout('H', false);
return 0;
}- 在调用函数时更加方便
- 需要注意默认实参造成的函数调用二义性
默认实参必须出现在函数列表的最右边
- 所有的默认实参必须是"从右到左"的.
默认实参的二义性
我们将上面的代码稍作修改.
#include <cstdio>
void HadesCout(int iNum = 100, bool isPrintCrLf = true)
{
printf("%d", iNum);
if (isPrintCrLf)
printf("\n");
}
void HadesCout(char* szVal = "Hades Studio", bool isPrintCrLf = true)
{
printf("%s", szVal);
if (isPrintCrLf)
printf("\n");
}
int main()
{
// 猜猜结果?
HadesCout();
return 0;
}此时调用
HadesCout就会出错, 因为它产生了二义性.
二义性
在调用函数时, 编译器无法找到与之
唯一匹配的函数, 就会造成二义性.
解决方法使之唯一匹配
- 在使用默认实参或者重载的时候, 尽量进行精准唯一的匹配
在调用时, 确定它的精确参数.
- 传递参数的时候, 进行参数的精确确定.
- 修改默认实参或重载函数.
内联函数
inline关键字可以把函数做成内联函数.
当函数被成为内联函数后, 在调用的时候就会展开(代码).
它不会新建栈空间来进行call
优缺点:运行的效率会大大的提升生成的体积会膨胀.
标记inline关键字的函数并不是100%会成为内联函数
它会根据编译器的判断来完成
不加
inline则不会成为内联函数.
只有加了inline关键字, 编译器才会尝试去讲函数变为内联函数.
判定标准:栈的使用程度
如果函数异常庞大, 对栈的使用非常大, 该函数不会成为内联函数
- 因为内联函数可以提升运行效率
- 提升call的时间
- 分配栈可以在统一的地方进行.
- 但是如果内联函数导致外部效率下降, 则得不偿失.
代码相对简单(展开度少)
- "简单" 表示 "调用层次" 少.
- 也就是 "函数调用" 少.
inline会有类型的检测, 内联函数还是一个函数
这是inline和define最大的不同, 替换终究只是替换
代码膨胀
仅作了解
在预处理的时候, 我们会生成许多代码展开
比如,
#include会被展开
#define会被展开
inline会被展开
泛型会被展开
....
在代码膨胀之后, 在C++中会造成一些影响.
比如在调试的时候, 出现了某个编译器生成的代码的错误, 但是我们并没有写这个函数.类型转换
在C语言中, 有如下转换方式
- 强制转换
隐式转换
- 隐式转换非常危险
- 建议在隐式转换的时候, 变为强制转换
在C++中, 我们的转换方式如下
- 隐式转换, C语言风格的强制转换
#include <iostream>
int main()
{
// 会产生隐式转换
int iNum1 = 1.0003;
// 所以我们经常会进行强制转换(C模式/C风格)
int iNum2 = (int)1.0003;
return 0;
}static_cast, C++风格式的转换
- C++ 模式/C++ 风格的转换
- 注意, 它不是强制转换
- 它只是表示转换
- 经常用于基类指针指向派生类指针时使用
#include <iostream>
int main()
{
int iNum3 = static_cast<int>(1.0003);
return 0;
}const_cast, 常量性转换
- 它在特定情况下使用
- 可以使 const 的变为 非const 的.
- 也就是说, 它可以移除对象的常量性.
- 但是转换之后, 还是不能修改内容.
主要适用于
- 参数的匹配
- 消除语法上的错误
- 用来不实现const版本
#include <iostream>
int main()
{
// 此处无举例...
return 0;
}reinterpret_cast, 强制转换
- 真正的强制转换
- 基于二进制层面的转换, 相当于拿指针进行拷贝
- 尽量不要使用
- 非常危险!!!
#include <iostream>
int main()
{
int iNum4 = 10;
char* szStr = "Hades Studio";
iNum4 = reinterpret_cast<int>(szStr);
// 转换过后会, num变为szStr指向的地址..
int* pNum = nullptr;
// 不能够编译通过
// char* pSz = pNum;
// 不能够编译通过
// char* pSz = static_cast<char*>(pNum);
// 可以使用
char* pSz = reinterpret_cast<char*>(pNum);
return 0;
}dynamic_cast, 类型推导转换
- 仅作了解
#include <iostream>
int main()
{
// 此处无例子
return 0;
}补充
static_cast, dynamic_cast, reinterpret_cast 和 (char)int 类型的强制转换我们有2种风格的强制转换
(char)int 这种为C风格的转换它是比较暴力的
有安全的, 也有非安全的.
不管怎么样都会转换成功!简单, 暴力static_cast
相对来说是安全的
dynamic_cast
暂时不表
reinterpret_cast
非常危险, 是不安全的.
它是开放的, 并不禁止这种转换行为.
未完待续如有错误,请提出指正!谢谢.
本文由 花心胡萝卜 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: 2017-01-04 at 01:50 am