现在的位置: 首页 > 综合 > 正文

函数重载与默认参数小结

2013年05月27日 ⁄ 综合 ⁄ 共 2800字 ⁄ 字号 评论关闭
文章目录

引入:

为什么要函数重载?

这个问题其实就是为了解决函数名字的冲突问题,因为假如有一个方法是动作洗, 那么如果是洗车洗衣服洗袜子都得是具体的名字, 这样多不好呀!

必然性:

名字写得烦也就算了,不是必然性的, 但是构造函数的实现,如果要需要实例化多重或者是多类的实例怎么办,一样得必须重载

为什么不能用返回值重载?

这个问题的答案就是一般编译器内部都会将函数重新取一个名字,常用方法都是函数名+ 参数类型1 + 参数类型2 + 参数类型3 + 。。。
看到了吧,新的名字根本就没有返回值, 所以重载返回值是不行的,c++也是禁止了的
更糟糕的一个问题是连写程度的都不知道会调用哪个函数

为什么函数需要默认参数?

这个问题的答案其实可以归结为上面那个问题,当函数被重载了多个之后,那么必然参数也是各种各样的(重载只能动参数)可能有一大堆的函数就一点儿不同,却得每次调用都需要些一堆的参数, 这个我是不想这样做的,所以就用这个方法解决问题

深入:

类型安全连接

编译器生成可执行文件的时候是编译 - 》连接。
而且编译的时候为了省时间是单个文件编译的,就是一个文件就是一个编译单元, 然后再用连接器将所偶的编译单元连接起来重新生成可执行文件,就是因为这样的制,也导致了一点儿点儿的大问题
假如现在有两个文件,其中1.cpp中有如下定义
//1.cpp
void oyl(int v){}
而2.cpp有如下声明:
void oyl(char v);
由于是单个文件的编译机制,那么1.cpp, 2.cpp都会编译成功,如果在c中,链接也会成功,所以在c的编译器中会产生一个找到胡子白的难发现的bug, 而在c++的编译器中,由于在  上面(为什么不能用返回值重载?)中的这种机制将发现这个错误,从而类型安全链接。所以用c++编译器找找c项目中的bug估计很爽

重载的例子

略了好了

默认参数例子

同上好了

选择重载还是默认参数呢?

表示这个就别略了

自写一个string类:

1. mem.h, 这个是自己写的内存管理的头文件:

/*
encoding by ygqwan
in 2013/ 8 / 10
*/

//: mem.h
#define MEM_H
typedef unsigned char byte;

class Mem
{	
	byte * mem;                                //这块内存的首地址
	int size;                                  //这块内存的大小
	void ensureMinSize(int minSize);           //确保内存大小值最次也比minSize大

public:
	Mem();
	Mem(int sz);                               //构造一个大sz 的内存块
	~Mem();
	int msize();
	byte *pointer();                           //返回内存块儿的首地址
	byte *pointer(int minSize);                //一样的作用,只是这里多了一步增加内存大小的作用
};

2. mem.cpp  对mem.h里面的声明进行定义:

/*
encoding by ygqwan
in 2013/ 8 / 10
*/


//:mem.cpp   主要做内存的分配和相关处理,但是这里的内存是只会不不会减
#include "mem.h"
#include <cstring>
using namespace std;

Mem::Mem(){
	mem = 0;
	size = 0;
}

Mem::Mem(int sz){
	mem = 0;
	size = 0;
	ensureMinSize(sz);
}
Mem::~Mem(){
	delete []mem;
}

int Mem::msize(){
	return size;
}

void Mem::ensureMinSize(int minSize){
	if(size < minSize){
		byte *newmem = new byte[minSize];
		memset(newmem + size, 0, minSize - size);
		memcpy(newmem, mem, size);
		delete []mem;
		mem = newmem;
		size = minSize;
	}
}
byte* Mem::pointer(){
	return mem;
}
byte* Mem::pointer(int minSize){
	ensureMinSize(minSize);
	return mem;
}

3. MyString.cpp , 这个就是自己的string类了:

/*
encoding by ygqwan
in 2013/ 8 / 10
*/
#include "mem.h"
#include <cstring>
#include <iostream>
using namespace std;

class MyString
{
	Mem *buf;
public:
	MyString();
	MyString(char * str);
	~MyString();
	void concat(char * str);                        //在原有串的后面增加str串
	void print(ostream & os);
};

MyString::MyString(){ buf = 0;}

MyString::MyString(char *str){
	buf = new Mem(strlen(str) + 1);
	strcpy((char *)buf->pointer(), str);
}
void MyString::concat(char * str){
	if(!buf)
		buf = new Mem();
	strcat((char *)buf->pointer(buf->msize() + strlen(str)), str);
}
void MyString::print(ostream & os){
	if(!buf) return;
	os << buf->pointer() << endl;
}

MyString::~MyString(){
	delete buf;
}

int main()
{
	
	MyString * s = new MyString("oyl");
	s->concat("wan");
	s->print(cout);

	MyString * s2 = new MyString();
	s2->concat("...wan");
	s2->print(cout);
	return 0;
}

MyString(char *str)
{
	if(*str == 0)
		buf = 0;
	return;
}

从上面的代码可以看到如下特性:

MyString()和MyString(char *str)同时都有, 无参数的主要是为了同时创建很多空的string, 这里的时间花销就是给buf付了一个初始值0而已, 如果我们使用默认参数的形式就不一样了, 花销就大了
不能把默认参数作为一种标志去决定执行函数的哪一块, 这是铁一般的定则, 避免这样的做法就是把函数分开或者重载多个,就上面的MySstring就重载了,而不是使用默认参数去决定执行函数的哪一块儿

大放送

默认参数的一个重要应用就是在开始定义函数的时候用了一组参数, 而是用了今年后,客户没事儿找事儿做说要增加新的功能, 那么很有可能需要增加这个函数的参数的个数, 那么这个时候就可以将新增加的参数都作为默认参数, 这样就完全不用去改变以前调用这个函数的代码了,省事不少呀

总结:

有点儿结巴了

抱歉!评论已关闭.