对比C语言中的结构体
在C语言中,我们经常定义结构体来作为数据结构,而C++也支持定义结构体。C++中的结构体与C语言中的结构体主要有以下几点区别:
1.C语言需要使用struct structNme来定义结构体,而C++可以直接用structName来定义结构体名。(C语言可通过typedef来为结构体取别名)
#include <iostream>
using namespace std;
struct Point {
int x, y;
};
int main() {
Point p1;
p1.x = 1;
p1.y = 0;
return 1;
}
2.C语言中不能初始化结构体成员,而C++中可以。
#include <iostream>
using namespace std;
struct Point {
int x=1, y;
};
int main() {
Point p1;
cout << p1.x << endl;
return 1;
}
1
3.C语言中结构体不能有成员函数,而C++中可以有。
struct Point {
int x=1, y;
void printxy() {
cout << "x = " << x << endl;
cout << "y = " << y << endl;
}
};
4.C语言结构体中不能声明静态变量,而C++可以。
struct Point {
static int x;
};
5.C语言结构体中的变量不能有访问修饰符,只能是public,而C++中的可以有。
struct Point {
private: int x;
};
6.C语言中结构体不能继承,而C++中可以。
#include <iostream>
using namespace std;
struct Point {
int x;
};
struct Point2D :Point {
int y;
};
int main() {
Point2D p1;
p1.x = 1;
p1.y = 2;
return 1;
}
构造函数与析构函数
为什么需要构造函数
我们知道,对于未初始化的全局变量,编译器会自动将其初始化未0;而未初始化的局部变量,它的值则是未知的。因为全局变量在程序开始运行之后地址便不会发生改变,因此程序启动时将其初始化未0不会浪费多少时间。而局部变量则不同,局部变量的存储空间是动态分配的,每次调用函数时都可能是不同的,如果每次调用该函数都将局部变量进行初始化,则会带来许多的时间耗费。因此,未显式被初始化局部变量的值是未知的,它的值取决于该地址之前的值。
结构体和对象的初始化则是比变量的初始化更为复杂,结构体和对象中可能含有指针等必须进行初始化的成员,有的可能还涉及到动态内存分配等操作。因此,通过定义一个函数来显式的对结构体或者对象进行初始化是有必要的。我们通过自定义一个成员函数来对结构体进行初始化是一种可行的方式,在每次定义结构体之后都利用该函数对结构体进行初始化即可。但这种方式未免显得有些麻烦,由于缺少强制性,程序员可能会忘记调用该函数。因此,C++提供了构造函数,它在结构体或对象定义的时候被自动调用来进行初始化。
构造函数的特点
构造函数有以下几个特点:
1.构造函数是一类特殊的成员函数
2.构造函数的名字和结构体/类的名字相同
3.构造函数可以重载
4.如果不编写构造函数,编译器会自动生成一个构造函数
下面是一个简单的例子:
#include <iostream>
using namespace std;
struct Point {
public:
int x, y;
Point(int, int);
};
Point::Point(int a, int b) {
x = a;
y = b;
}
int main() {
Point p1(2,3);
cout << p1.x << " " << p1.y << endl;
return 0;
}
上例中为结构体Point定义了构造函数,函数有两个参数,用于给成员变量赋值。
此构造函数还可以有如下简单写法:
struct Point {
public:
int x, y;
Point(int, int);
};
Point::Point(int a, int b) :x(a), y(b) {}
这里的x(a), y(b)表示x=a, y=b,还可以进一步简化为:
struct Point {
public:
int x, y;
Point(int a, int b) :x(a), y(b) {};
};
构造函数的重载
构造函数支持重载,它们的名字相同,根据参数列表不同调用不同的构造函数:
struct Point {
public:
int x, y;
Point(int a, int b) :x(a), y(b) {};
Point(int a) :x(a), y(a) {};
};
当使用Point(2)创建结构体时,a=b=2
当使用Point(2, 3)创建结构体时,a=2 b=3
析构函数
另外,C++中还有另一个和构造函数功能相反的函数–析构函数。它的主要作用是释放资源,清理善后。例子如下:
#include <iostream>
using namespace std;
struct Point {
public:
int x, y;
Point(int a, int b) :x(a), y(b) {};
Point(int a) :x(a), y(a) {};
~Point() {cout << "Goodbye World" << endl;};
};
int main() {
Point p1(2, 2);
cout << p1.x << " " << p1.y << endl;
return 0;
}
2 2
Goodbye World
上面结构体中的~Point函数为析构函数,在主函数执行完的时候会调用这个函数来处理一些善后事宜。这里自定义了析构函数,于是在程序结束之前会调用该析构函数,从而打印出析构函数中的"Goodbye World"。注意析构函数不能重载!
结构体与类的区别
实际上,C++中的结构体与类无太大区别,我们可以通过struct实现class的所有功能。而struct与类最大的区别是默认访问权限。
struct的默认访问权限为public,而class的默认访问权限为private。
下面通过例子说明:
#include <iostream>
#include <string>
using namespace std;
struct Array{
//结构体默认访问权限为public
int length;
Array(){};
void setAge(int Length) { this->length = Length; };
};
class Cat {
//类默认访问权限为private
int age;
public:
Cat(){};
void setAge(int Age) { this->age = Age; };
};
int main() {
Array a;
Cat miao;
a.length = 10;//可以直接赋值
miao.setAge(10);//可以通过public修饰的成员函数赋值成员变量
return 0;
}
上面的例子定义了Array结构体和Cat类,Array中的成员变量和成员函数默认访问权限为public,而Cat中的默认权限为private。
为了提高程序的可读性,我们应该主动设置访问权限而不是依靠默认权限!
在上面这个例子中,我利用结构体来定义数组,而利用类来定义猫。这显然可以更好的符合我们的认知,因此我们在选择使用结构体还是类的时候可以考虑要定义的对象是一种数据结构还是一类事物。
总结
(1) C++中的结构体比C语言中的结构体更加的灵活。
(2) C++中的结构体可定义构造函数和析构函数。
(3) C++中的结构体和类的性质与用法大多一致,但成员变量和成员函数的默认访问权限不同。
(3) C++中的结构体多用于表示数据结构,而类多用于表示一类事物。