C++类的声明和对象的创建
类是创建对象的模板,一个类可以创建多个对象,每个对象都是类类型的一个变量;创建对象的过程也叫类的实例化。每个对象都是类的一个具体实例(Instance),拥有类的成员变量和成员函数。
与结构体一样,类只是一种复杂数据类型的声明,不占用内存空间。而对象是类这种数据类型的一个变量,占用内存空间。
类的声明
类是用户自定义的类型,如果程序中要用到类,必须先进行声明,或者使用已存在的类(别人写好的类、标准库中的类等),C++语法本身并不提供现成的类的名称、结构和内容。
一个简单的类的定义:
1
2
3
4
5
6
7
8
9
10
|
class Student{
//成员变量
char *name;
int age;
float score;
//成员函数
void say(){
printf ( "%s的年龄是 %d,成绩是 %f\n" , name, age, score);
}
};
|
该例创建了一个Student类,它包含了3个成员变量和1个成员函数。
class是C++中的关键字,用于声明一个类;紧接 class 关键字之后的是我们自定义的类名 Student;由{ }包围的是类体。声明类时不能对成员变量进行初始化,只有在创建对象以后才能赋值。
类可以理解为一种新的数据类型,该数据类型的名称是 Student。与 char、int、float 等基本数据类型不同的是,Student 是一种复杂数据类型,可以包含基本类型,而且多了很多基本类型中没有的特性。
需要注意的是:在类声明的最后有一个分号(;),它是类声明的一部分,表示类声明结束了,不能省略。
创建对象
声明了 Student 数据类型之后,就可以用它来定义变量了,如:
1
|
Student LiLei; //创建对象
|
该语句声明了一个名字为 LiLei、数据类型为 Student 的变量。这和:
1
|
int a; //定义整形变量
|
语句定义了一个整型变量表达的意思是类似的。而 LiLei 这个变量我们称之为 Student 类的对象。
在定义类的对象时,class 关键字可要可不要。但出于习惯我们通常都会省略掉class关键字,例如:
1
2
|
class Student LiLei; //正确
Student LiLei; //同样正确
|
创建类的对象时,除了能定义单个变量以外,还可以定义一个数组或者指针。例如:
1
2
|
Student all_student[100];
Student *pointer;
|
第一条语句定义了一个 all_student 数组,该数据拥有100个元素,每个元素都是 Student 类型。第二条语句定义了一个 Student 类型的指针 pointer,该指针可以指向 Student 类型的变量(对象),用法和普通指针一样。
声明类的同时创建对象
和结构体(struct)类似,你可以先声明类,然后再创建对象,也可以在声明类的同时创建对象。如下所示:
1
2
3
4
5
6
7
8
9
10
|
class Student{
//成员变量
char *name;
int age;
float score;
//成员函数
void say(){
printf ( "%s的年龄是 %d,成绩是 %f\n" , name, age, score);
}
}stu1, stu2;
|
这个时候你也可以省略类名,直接创建对象。如下所示:
1
2
3
4
5
6
7
8
9
10
|
class {
//成员变量
char *name;
int age;
float score;
//成员函数
void say(){
printf ( "%s的年龄是 %d,成绩是 %f\n" , name, age, score);
}
}stu1, stu2;
|
直接定义对象,在C++中是合法的、允许的,但却很少用,也不提倡用。
一个完整的示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
#include <stdio.h>
//类可以在所有函数之外定义
class Student{
public : //类包含的变量
char *name;
int age;
float score;
public : //类包含的函数
void say(){
printf ( "%s的年龄是 %d,成绩是 %f\n" , name, age, score);
}
};
int main(){
//创建对象
Student stu;
stu.name = "小明" ;
stu.age = 15;
stu.score = 92.5f;
stu.say();
//定义指针
Student *pt_stu = &stu;
pt_stu->name = "李雷" ;
pt_stu->age = 16;
pt_stu->score = 80;
pt_stu->say();
return 0;
}
|
运行结果:
1
2
|
小明的年龄是 15,成绩是 92.500000
李雷的年龄是 16,成绩是 80.000000
|
public 是C++中的关键字,用来修饰成员变量和成员函数,表示它们是公有的。我们将在下节详细讲解 public,这里只需要知道,只有 public 后面的成员变量和成员函数才能被创建的对象访问到。像本节开头的例子,没有使用 public,那么创建对象后就不能使用任何成员。
main 函数中首先创建了一个对象 stu,然后又定义了一个 Student 类型的指针变量。可以发现,和结构体(struct)类似,一个对象通过成员选择符”.“来访问成员变量和成员函数,而指针变量通过指针操作符”->“来访问成员。
对象指针和结构体指针类似。
注意:对象指针指向的是一个具体的对象,而不是类。下面的写法是错误的:
1
2
|
Student *pt;
pt = &Student;
|
C++对象成员的引用
在程序中经常需要访问对象中的成员。访问对象中的成员可以有3种方法:
- 通过对象名和成员运算符访问对象中的成员;
- 通过指向对象的指针访问对象中的成员;
- 通过对象的引用变量访问对象中的成员。
通过对象名和成员运算符访问对象中的成员
例如在程序中可以写出以下语句:
1
|
stud1.num=1001; //假设num已定义为公用的整型数据成员
|
表示将整数1001赋给对象stud1中的数据成员num。其中“.”是成员运算符,用来对成员进行限定,指明所访问的是哪一个对象中的成员。注意不能只写成员名而忽略对象名。
访问对象中成员的一般形式为:
对象名.成员名
不仅可以在类外引用对象的公用数据成员,而且还可以调用对象的公用成员函数,但同样必须指出对象名,如:
1
2
|
stud1.display( ); //正确,调用对象stud1的公用成员函数
display( ); //错误,没有指明是哪一个对象的display函数
|
由于没有指明对象名,编译时把display作为普通函数处理。应该注意所访问的成员是公用的(public )还是私有的(private ),只能访问public成员,而不能访问private成员。如果已定义num为私有数据成员,下面的语句是错误的:
1
|
stud1.num=10101; //num是私有数据成员,不能被外界引用
|
在类外只能调用公用的成员函数。在一个类中应当至少有一个公用的成员函数,作为对外的接口,否则就无法对对象进行任何操作。
通过指向对象的指针访问对象中的成员
前面已经介绍了指向结构体变量的指针(详情请猛击:指向结构体变量的指针),可以通过指针引用结构体中的成员。用指针访问对象中的成员的方法与此类似。如果有以下程序段:
1
2
3
4
5
6
7
8
9
|
class Time
{
public : //数据成员是公用的
int hour;
int minute;
};
Time t, *p; //定义对象t和指针变量p
p=&t; //使p指向对象t
cout<<p->hour; //输出p指向的对象中的成员hour
|
在p指向t的前提下,p->hour,(*p).hour和t.hour三者等价。
通过对象的引用变量来访问对象中的成员
如果为一个对象定义了一个引用变量,它们是共占同一段存储单元的,实际上它们是同一个对象,只是用不同的名字表示而已。因此完全可以通过引用变量来访问对象中的成员。
如果已声明了Time类,并有以下定义语句:
1
2
3
|
Time t1; //定义对象t1
Time &t2=t1; //定义Time类引用变量t2,并使之初始化为t1
cout<<t2.hour; //输出对象t1中的成员hour
|
由于t2与t1共占同一段存储单元(即t2是t1的别名),因此t2.hour就是t1.hour。