C++与C#对比学习:函数(二)返回值,默认实参.this指针

函数返回值

我们定义函数时会指定一个返回值类型,那在函数体中必须返回一个匹配的类型,或者隐式转换后能匹配的类型.不过有时存在这样的情况,如果函数体中存在一些分支语句,有些情况是可以返回一个值,但有时不会返回值.还是举个例子吧.

有如下C++函数

int FunArwen(int a , int b)

{

if(a < b)

return 888;

}

很显然,上面的函数有时会返回一个值,但有时又不会.

int result = FunArwen(4,5); //这时结果是888;

int res= FunArwen(5,4);

//这时函数不会有返回值,不过我在VS中运行得到res为5,貌似返回了第一个参数的值.不知道为啥是这个值,没太搞懂.

//不过反正这肯定是个错误的结果.

在C++中上面的函数编译时会有一个警告信息"not all control paths return a value",而在C#中上面的函数不能通过编译的,会报错,"not all code paths return a value".

你必须写成if (a < b) return 888 ;

else return 44;

或者if(a < b) return 888; return 444;

这样才能编译通过

C#针对C++中的很多地方都做了一些改进,多做了一些检查.使你写出来的代码更不容易出错.其实一个编程语言的发展很多时候关注的一是,简化一些复杂的语法,使你能用更少的代码实现更多的功能.另一个是多做一些检查,要编译期间就给你检查出一些错误来.当然准确的讲有些错误也不是真正的错误,只要有潜在的犯错可能就当作错误处理了.

我们平时不是常讲软件测试嘛,其实编译器做的工作也算是测试的一种,给你把代码中的语法错误找出来.如果任何错误都能在编译期间都找出来自然是最完美的,不过编译器可没这么聪明.很多运行时错误它是没法检测出来的.

C++返回局部函数体中局部变量指针或引用的问题

另外值得注意的是在C++中如果返回结果是函数体中的局部指针或引用类型.则会出错,因为函数体中的局部变量一超过作用域就会被释放了.所以指针就变成野指针了.不知道指到哪去了.举个例子

int* GetResult( )

{

int num = 110;

int* ip = &num;

return ip;

}

int* p = GetResult(); //这样做是错误的,不过有时错误的操作也会得到正确的结果.

//你运行时可能出现运行时错误,可能运行正确得到个错误的结果,有时还可能得到正确的结果.反正我在VS中试的时候是得到个正确的结果的.

因为num超出作用域之后就告诉系统那块内存它不要了,系统可以把那内存分配给别人用了.不过如果那内存暂时还没被分给谁,那里面的值还仍然在,所以你通过指针去访问那个值时可能还能得到个正确的值

默认实参

假如某个函数的参数有很多个,我们调用时要传那么多个参数进去非常麻烦,而且有些参数不那么重要,我们整个啥默认值就行.你首先想到的可能是来个函数重载,整很多个函数出来,但参数个数都不一样.显然这确实是一个办法.但实现的不够优美.在C++中有个默认实参的做法能更好的解决这问题.举例

void Register(string userName = "打酱油的"

,string pwd = "123"

, int age = 18

)

{

//do something

}

这样我们调用函数时可以像下面那样

Register();

Register("arwen");

Register("arwen","911");

Register("weiwen","110",24);

上面那样调用都正确,不过你这样调用就不行

Register("wei", 24); //会出错.因为系统是从左到右去匹配.你传两个参数它只会去匹配userName和pwd

C#中没有默认实参

不过有点遗憾的是C# 2.0, 3.0中都没有提供这个功能.据说c# 4.0有提借这功能.不过我还从没用过4.0.微软的东西更新太快,要老想去跟着赶时髦会很累的啊.还是老实的把基础打好再说

This 指针

举个例子,有C++类Arwen

class Arwen

{

private:

int age;

int height;

public:

void SetAge(int age)

{

this ->age = height;

}

void SetHeight(int hgt)

{

height = hgt;

}

}

Arwen wen;

int hgt = 111;

wen.SetHeight(hgt); //我们知道每个类的函数跟static变量一样是不属于某个实例的,所以的实例对象都使用共一个函数.函数是保存在代码区.那我们这样调用函数时,怎么能找到函数呢?实际上你像上面这样调用一个函数时编译器会默认把它 转换成

Arwen::SetHeight(&wen , hgt);

然后给height赋值就是这样 wen.height = hgt; //默认情况都是给自成员变量前加个实例对象做前缀.&wen也就是this指针了.

但如果成员变量和传的参数同名了就必须显式加this指针.

像SetAge中 this->age = age;

const函数

我们可以在函数后面加个const,例如void SetAge(int age) const { this->age = age;}

Arwen wen;

int age = 222;

wen.SetAge(age); //此时出错了.

因为编译器把上面的调用中的this指针转化成指向const类型的指针了,所以不用this->age = age;这样去修饰指针指向的值了.

C#中的this的用法和原理跟C++差不多.虽然C#中没有指针的概念,但我猜实际上后台很多实现最终都是通过指针实现的.估计C#的编译器也是用C++和C开发的吧.连微软的操作操作都是C++和C开发的.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值