C++ for C Programmers--Part one


注:非特别注明,代码均是C++

1.引用(Reference)

在C语言中,一个函数想要修改函数外的变量的值,需要用到指针,例如下面这个C语言函数:

void swap(double* A, double* B) //C语言
{
	double temp;
	temp = *A;
	*A = *B;
	*B = temp;
}

使用这个函数时:

swap(&a, &b); //C语言

在C++中,可以用“引用”来简化这一操作,例如:

void swap(double& A, double& B)
{
	double temp;
	temp = A;
	A = B;
	B = temp;
}

使用这个函数时:

swap(a, b);

C++检测到“&”时,就会知道函数需要对本地的变量直接进行操作,而不是一个copy。

2.内联(inline)

在C语言中经常会定义一些宏,比如:

#define max(a,b) (a)>(b)?(a):(b) //C语言

这样的定义虽然可以提高代码执行效率,但是会带来许多问题(边际效应)。
C++中使用内联(inline)来处理类似的情况,既能提高代码效率,又能避免许多错误,例如:

inline int max(int a, int b)
{
 return a > b ? a : b;
}

具体请参考:C++ 关键字 inline详细介绍

3.类(class)

举例如下:
创建一个Point类型,表示在直角坐标系下的一个点(x,y)。

class Point
{
public:
	double getx() { return x; }
	double gety() { return y; }
	void setx(double v) { x = v; }
	void sety(double v) { y = v; }
private:
	double x, y;
};

在此定义了四个public函数以及两个private坐标。
类成员可以任意访问private,而非类成员则不行。public表示外部可以任意访问。
下面是一个使用例子:

int main()
{
	Point A, B;
	A.setx(1);
	A.sety(2);
	B.setx(3);
	B.sety(4);
	return 0;
}

外部只能通过对public四个函数的访问来初始化Point类型的A和B数据。

4.重载(overload)

1. 函数重载

C++支持两个函数使用相同的函数名,而不会出现混淆,这是因为C++会根据函数的类型(type)实参的数目(number of arguments) 去区分应该使用哪个函数。
例如:

void swap(double* A, double* B)
{
	double temp;
	temp = *A;
	*A = *B;
	*B = temp;
}

void swap(int* A, int* B)
{
	int temp;
	temp = *A;
	*A = *B;
	*B = temp;
}

调用swap函数时,C++自动根据传入实参的数据类型选择相应的函数执行。

2.运算符重载

例子1

在类(class)中我们定义了一个Point类,现在我们想要用“+”对这个类进行操作,比如A(1,2)+B(3,4)=C(4,6)。用“<<”对Point类进行打印,代码如下:

Point operator+(Point& x, Point& y)
{
	Point sum;
	sum.setx(x.getx() + y.getx());
	sum.sety(x.gety() + y.gety());
	return sum;
}

用上面的方式重载双目运算符“+”,加号两边都是Point类型的数据(使用引用(reference)避免产生copy),返回的数据类型也是Point。

ostream& operator<<(ostream& x, Point& y)
{
	cout << '(' << y.getx() << ',' << y.gety() << ')';
	return cout;
}

同理可以重载“<<”,注意到其中一个输入和输出都是ostream类型。
重载好两个运算符之后,下面是一个使用例子:

int main()
{
	Point A, B, C;
	A.setx(1);
	A.sety(2);
	B.setx(3);
	B.sety(4);
	C = A + B;
	cout << C;
	return 0;
}

例子的前半部分与之前一样,初始化A(1,2)与B(3,4),使用“+”运算符后,C被赋值为(4,6),然后通过“<<”输出至控制台。

例子2

先看代码:

typedef enum days {SUN, MON,TUE, WED, THU, FRI, SAT} days;

inline days operator++(days& d)
{
    return d = static_cast<days>(static_cast<int>(d + 1) % 7);
}

上面定义了一个枚举类型days,想要通过++运算符达到语义上的“增加一天”的效果(例如:输入:SUN++,输出:MON),因为days是自定义的类型,c++无法识别,所以要重新定义++运算符的功能(重载)。重载后,便可以用++运算符对days类型的数据进行操作了。示例如下:

void main()
{
    days d = SUN;
    ++d;
}

结果d为days类型的MON。

5.范型(Generic)

范型就是把类型参数化,对于一些结构上相同,只是数据类型不同的函数可以整合到一起(比如重载的函数)。
下面是一个例子,实现一个sum功能:

template<class summable>
summable sum(const summable A[],int length)
{
	summable sum = 0;
	int i;
	for (i = 0; i < length; i++)
	{
		sum += A[i];
	}
	return sum;
}

在函数声明前需要加上template,对于想要参数化的类型,用一个summable(自定义)去代替,这样只用写一个函数就可以实现多种数据类型的求和了。

6.默认参数(Default Parameter)

在C++中定义函数时,可以给到形参一个默认值,在使用函数时若不传入实参则会使用这个默认值。
例如:

inline int sum(int n, int *d,int p = 0)
{
	for (int i = 0; i < n; ++i)
		p += d[i];
	return p;
}

使用函数时如果为:

accum = sum(N, data);

那么p初始化为0。
如果为:

accum = sum(N, data, 10);

则p初始化为10。

7.Stastic_Cast

用于安全地转换数据类型,例如:

template<class T1, class T2>
void copy(const T1 source[], T2 destination[], int size)
{
	for (int i = 0; i < size; i++)
		destination[i] = static_cast<T2>(source[i]);
}

可以安全地将T1类型的数据拷贝为T2类型的数据。

参考资料

Coursera课程:C++ for C Programmers

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值