16 类的声明、对象的定义及使用
1 类的声明
类是创建对象的模板,一个类可以创建多个对象,每个对象都是类类型的一个变量;创建对象的过程也叫类的实例化。每个对象都是类的一个具体实例(Instance),拥有类的成员变量(属性)和成员函数(方法)。也就是说,需要先声明一个类,才能定义对应的对象。
类的声明格式如下:
class 类名{
private:
成员变量和成员函数
protected:
成员变量和成员函数
public:
成员变量和成员函数
};
其中, class
是定义类的关键字, public
、protected
、private
三个关键字是用来控制成员变量和成员函数的访问权限的。这三个关键字的用法,将在 “封装” 章节具体讲解,现在,我们只用 public
关键字。
请不要忘记最后的分号
让我们看一个学生类的例子:
class Student {
public:
string name;
int age;
int score;
void say() {
cout << "我是" << name << ",我今年" << age << "岁了,我的成绩是" << score << "分。" << endl;
}
};
以上代码,声明了一个叫做 Student
的类,类的名字一般使用大驼峰命名法,即所有单词的首字母大写。类名后 {}
中的内容被称为 “类体” 。
类的成员函数除了可以直接定义在类体中,还可以仅在类体中存放函数原型,然后在类体外,给出函数的具体定义。此时,定义函数时,需要使用作用域运算符 ::
说明现在定义的函数属于哪个类。
class Student {
public:
string name;
int age;
int score;
void say();
};
void Student::say() {
cout << "我是" << name << ",我今年" << age << "岁了,我的成绩是" << score << "分。" << endl;
}
定义在类体内的成员函数,默认是内联函数(
inline
);而定义在类体外的成员函数,默认不是内联函数,除非显式使用inline
关键字。
class Student {
public:
string name;
int age;
int score;
void say();
};
inline void Student::say() {
cout << "我是" << name << ",我今年" << age << "岁了,我的成绩是" << score << "分。" << endl;
}
2 对象的定义
- 先声明类,再定义对象。
class Student {
public:
string name;
int age;
int score;
void say() {
cout << "我是" << name << ",我今年" << age << "岁了,我的成绩是" << score << "分。" << endl;
}
};
……
Student stu1;
- 声明类的同时定义对象。
class Student {
public:
string name;
int age;
int score;
void say() {
cout << "我是" << name << ",我今年" << age << "岁了,我的成绩是" << score << "分。" << endl;
}
}stu1;
3 访问对象成员
- 通过 对象名 访问对象成员,需要使用点运算符
.
。语法为:对象名.成员名
。 - 通过 指针 访问对象成员,需要使用箭头运算符
->
。语法为:指针名->成员名
。 - 通过 引用 访问对象成员,需要使用点运算符
.
。语法为:引用名.成员名
。
示例:
#include<iostream>
using namespace std;
class Student {
public:
string name;
int age;
int score;
void say();
};
void Student::say() {
cout << "我是" << name << ",我今年" << age << "岁了,我的成绩是" << score << "分。" << endl;
}
int main() {
Student stu1;
stu1.name = "张三";
stu1.age = 16;
stu1.score = 90;
cout << "学生姓名:" << stu1.name << endl;
stu1.say();
Student *stu_ptr = &stu1;
stu_ptr->name = "李四";
cout << "学生姓名:" << stu_ptr->name << endl;
stu_ptr->say();
Student &s = stu1;
s.name = "王五";
cout << "学生姓名:" << s.name << endl;
s.say();
return 0;
}
4 对象互相赋值
使用赋值号 =
连接两个对象,相对于对象的成员变量一一赋值,而不是让它们指向相同的内存地址。
5 对象作为函数参数
类作为一种数据类型,当然可以作为函数参数使用。但在 C++ 中,直接使用类做参数类型的话,函数中得到的对象,并不是传入的对象本身,而是原对象的属性一一复制后的新对象。
#include<iostream>
using namespace std;
class Student {
public:
string name;
int age;
int score;
void say() {
cout << "我是" << name << ",我今年" << age << "岁了,我的成绩是" << score << "分。" << endl;
}
};
void show(Student s){
cout << "s的地址:" << &s << endl;
s.say();
}
int main() {
Student stu1;
stu1.name = "张三";
stu1.age = 16;
stu1.score = 85;
cout << "stu1的地址:" << &stu1 << endl;
show(stu1);
return 0;
}
运行结果:
stu1的地址:0x6addbffac0
s的地址:0x6addbffb20
我是张三,我今年16岁了,我的成绩是85分。
stu1
与 s
的内存地址不同,因此它们不是同一个对象。这有一个好处,我们在这个函数中进行的操作,不会影响到原本的对象。但这需要开辟新的内存空间,初始化一个新的对象,而这个对象生命周期仅仅到这个函数结束,这个内存空间又需要释放。因此,这样的函数,运行效率会很差。
所以,大多数情况下,我们应该用 “引用” 或 “指针” 来作为函数参数,将已有对象本身引入函数。
将上面例子中,show
函数改成下面这样:
void show(Student &s){
cout << "s的地址:" << &s << endl;
s.say();
}
运行结果:
stu1的地址:0x54d7fffbe0
s的地址:0x54d7fffbe0
我是张三,我今年16岁了,我的成绩是85分。
此时,stu1
与 s
是同一个对象,我们在函数内对 s
进行的操作,就是对 stu1
进行的操作。
大家需要根据我们要实现的具体功能,来确定使用那种形式。