C++与C语言的一些不同
注:非特别注明,代码均是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类型的数据。