结构与类
1 . 结构的扩充
结构是 C 语言的一种自定义的数据类型, 在结构体中可以含有各种不同类型的数据。C + + 语言对结构类型进行了扩充, 它不仅可以含有不同类型的数据, 而且还可以含有函数。例如下面声明了一个复数的结构:
struct complex
{
double real;
// 复数的实部
double imag;
// 复数的虚部
void init ( double r, double i) // 给 real 和 imag 赋初值
{
read = r;
imag = i;
double realcomplex ( ) // 求复数的实部值
{
return real;
}
double imagcomplex( ) // 求复数的虚部值
{
return imag;
}
double abscomplex( ) // 求复数的绝对值
{
double t;
t = real * real + imag * imag;
return sqrt( t) ;
}
} ;
在这个声明为 complex 的结构中, 含有两个双精度数据 real 和 imag, 分别代表复数的实数部分和虚数部分, 另外含有四个属于结 构 complex 的函数: init ( )、realcomplex ( )、imagcomplex( )和 abscomplex ( )。init ( ) 函数用于给 real 及 imag 赋初值, realcomplex ( )、imagcomplex( ) 和 abscomplex ( ) 三个函数 分别用于 计算该复 数的实部 值、虚部值和 绝对值。
结构中的数据和函数都是结构的成员,分别称作数据成员和函数成员。在 C + + 中,通常把 函 数 成 员 称 为 成 员 函 数。 在 这 个 结 构 中, real 和 imag 是 数 据 成 员, init ( )、realcomplex( )、imagcomplex( )和 abscomplex( ) 是成员函数。为了访问这些成员函数,必须定义该结构类型的变量,然后像访问结构中的数据成员一样进行访问。
以下是这个例子的完整程序。
#include <iostream>
#include <math.h>
using namespace std;
struct complex
{
double real;
// 复数的实部
double imag;
// 复数的虚部
void init( double r, double i) // 给 real 和 imag 赋初值
{
real = r;
imag = i;
}
double realcomplex( ) // 求复数的实部值
{
return real;
}
double imagcomplex( ) // 求复数的虚部值
{
return imag;
}
double abscomplex( ) // 求复数的绝对值
{
double t ;
t = real * real + imag * imag;
return sqrt(t) ;
}
} A;
int main()
{
A.init(1.1,2.2);
cout << "real of complex A = "<< A.realcomplex( ) << endl;
cout << "imag of complex A = "<< A.imagcomplex( ) << endl;
cout << "abs of complex A = "<< A.abscomplex ( ) << endl;
return 0;
}
程序运行结果如下:
real of complex A = 1 .imag of complex A = 2 .abs of complex A = 2 .459675
在 C + + 中,一个结构的成员通常分为两类:私有成员 ( private )和公有成员 ( public )。
私有成员(包括数据和函数) 只能被该结构中的其它成员访问,而公有成员( 包括数据和函数)既可被结构内其它成员访问,也可被结构外的其它部分访问。
例如, 变量real 和 imag 只需要被该结构的成员函数访问, 则可声明为私有成员; 四个成员函数需要在结构体外被调用,则可声明为公有成员。因此, 结构 complex 可以改写为:
struct complex
{
private :
double real;
double imag;
public:
void init( double r, double i)
{
real = r;
imag = i;
}
double realcomplex( )
{
return real;
}
double imagcomplex( )
{
return imag;
}
double abscomplex( )
{
double t;
t = real * real + imag * imag;
return sqrt( t) ;
}
} ;
C + + 规定, 在缺省情况下,结构中的成员是公有的, 因此例 3 .1 结构 complex 中的成员都是公有的。
2 . 类的声明
C + + 提供了一种比结构类型更安全有效的数据类型———类。类是 C + + 的一个最重要的特性。类与结构的扩充形式十分相似,其一般形式如下:
class 类名{
[ private: ]
私有数据成员和成员函
public:
公有数据成员和成员函数
} ;
其中: class 是声明类的关键字, 类名是要声明的类的名字; 后面的花括号表示出类的声明范围;最后的分号表示类声明结束。
类的声明内容包括数据和函数。类中的数据和函数都是类的成员, 分别叫做数据成员和成员函数。
与结构的扩充形式一样,类的成员也分为私有成员和公有成员。私有成员用 private说明, private 下面的每一行,不论是数据成员还是成员函数, 都是私有成员。私有成员只能被该类的成员函数访问,这是 C + + 实现封装的一种方法, 即把特定的成员定义为私有的,就能严格地控制对它的访问。公有成员用 public 说明, public 下面的每一行都是公有成员。公有成员可被程序中的其它函数访问, 它们是类的对外接口。例如, 前面的结构complex 可以用类改写如下:
class complex
{
private :
double real;
double imag;
public:
void init( double r, double i)
{
real = r;
imag = i;
}
double realcomplex ( )
{
return real;
}
double imagcomplex( )
{
return imag;
}
double abscomplex( )
{
double t ;
t = real * real + imag * imag;
return sqrt(t) ;
}
} ;
实际上,在 C + + 中, 类 class 和结构 struct 是类似的, 因为 C + + 的结构与类一样, 都含有数据以及对这些数据进行的操作。它们的主要区别是缺省值不同:在类中, 缺省时成员是私有的; 而在结构中,缺省时成员是公有的。如果使用类, 则程序可以改写
如下:
# include <iostream>
# include <math.h>
using namespace std;
class complex
{
private :
double real;
double imag;
public:
void init( double r, double i)
{
real = r;
imag = i;
}
double realcomplex ()
{
return real;
}
double imagcomplex()
{
return imag;
}
double abscomplex()
{
double t ;
t = real * real + imag * imag;
return sqrt( t) ;
}
} A;
int main ()
{
A.init( 1.1, 2.2);
cout << "real of complex A = "<< A.realcomplex() << endl;
cout << "image of complex A = "<< A.imagcomplex() << endl;
cout << "abs of complex A = "<< A.abscomplex() << endl;
return 0;
}
可以看出,类和结构的功能基本上相同。那么在 C + + 中为什么要用类代替结构呢 ?原因是,在缺省的情况下, 类成员是私有的, 类提供了缺省的安全性。这一规定符合面向对象思想中数据隐藏的准则。数据隐藏使得类中的成员比一般的局部变量得到更好的保护。
说明:
- 类的声明中的 private 和 public 两个关键字可以按任意顺序出现任意次。但是, 如果把所有的私有成员和公有成员归类放在一起,程序将更加清晰。并且应该养成把所 有的私有成员放在公有成员前面的习惯,因为一旦用户忘记了使用说明符 private, 由于缺省值是private, 这将使用户的数据仍然得到保护。
- 除了 private 和 public 之外, 类中的成员还可以用另一个关键字 protected 来说 明。被 protected说明的成员称为保护成员, 它不能被外部函数使用, 但可以通过其它方 法使用它,将在第 4 章详细地介绍此方面内容。
- 数据成员可以是任何数据类型,但是不能用自动( auto)、寄存器 ( register) 或外部 ( extern)进行说明。
- 不能在类的声明中给数据成员赋初值, 例如:
class abc
{
private:
char a =′q′;
// 错误 int b = 33;
// 错误
public:
…
};
C + + 规定, 只有在类对象定义之后才能给数据成员赋初值。