在上一节中,我们编写了一个C++程序,创建了一个名字叫person的类。
方便起见,我们将这个类的所有成员的权限设置为了public。
#include <stdio.h>
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
class person {
//方便起见,类的成员都设置为了public
public:
char *name;
int age;
void printfInfo() {
printf("name = %s, age = %d\n", name, age);
}
};
int main(int argc, char **argv)
{
int i;
person persons[] = {
{
"zhangsan", 10,
},
{
"lisi", 16,
}
};
for (i = 0; i < ARRAY_SIZE(persons); i++) {
persons[i].printfInfo();
}
return 0;
}
那么,这个public是什么意思呢?
答:在上一节中,如果程序写完,不在person类中指定成员权限为public,那么就会使用默认的权限private。
权限为private的成员不可以被类外的函数所调用,此时在main函数中调用printInfo函数成员,设置name成员和age成员,编译时就会报权限错误。
而权限为public的成员则不会受到限制,类内外的函数均可调用。
类的成员权限
在C++中,类共有三种成员权限:
- private(仅供类内部的成员使用);
- protected(先不追究,后面讲继承的时候再介绍);
- public(类外部的成员也可以使用);
下面来试验一下private,在之前的代码基础上做两个修改:
- 将person类的名称改为Person(类的名称首字母需要大写);
- 将除printfInfo(函数成员)外的其他成员的权限改为private;
然后,在main函数中定义一个person类,名为per,试验一下此时是否可以在main函数中设置per的name成员。
#include <stdio.h>
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
class Person {
private:
char *name;
int age;
public:
void printfInfo() {
printf("name = %s, age = %d\n", name, age);
}
};
int main(int argc, char **argv)
{
Person per;
per.name = "zhangsan";
return 0;
}
这时候编译会报错,因为name成员的权限是private,不能在main函数中使用它。
此时,如果要设置name成员怎么办呢?
需要增加一个设置函数setName,通过这个函数来设置name成员。
设置不同权限的原因
那么,我们为什么要将有的成员设置为public,有的成员设置为private呢?
答:假设所有的成员都是public,那么成员的值就都可以通过外部函数来设置,这样有可能会设置错误的值,比如age被设为-1等。
将需要保护的变量设为private,通过权限为public的函数成员来设置和获取,在设置函数中添加对设置值的校验,可以增加程序的健壮性,防止数据被异常修改。
对象
在C++中,定义一个整型变量可以通过 int a; 来实现,定义一个Person类的变量可以通过Person per; 来实现。
但是在C++里,我们通常不会称呼类型为类的变量叫变量,而是叫对象,是这个类的对象。
int a;
Person per;
类的函数成员
在上面的代码中,我们创建了一个函数成员来设置名字,传入的参数名称为n,这样的命名不好识别它的作用,我们是否可以将他的名称改为name呢?
如果改为name,那么就会出现name = name;的语句,这样的语句是没有任何意义的。
那么,要怎么表示将类的name成员的值,设置为传入的name参数呢?
答:可以使用 this->name 来表示类的name成员,而传入的参数仍然叫name。
这里的 this 是一个指针,指向当前对象。
还有一个问题,我们传入的参数叫name,类的一个成员也叫name,这两个不是冲突了吗?编译器要怎么分辨我们使用的name,是哪个name呢?
答:根据就近原则来决定。我们在setName函数中使用name变量,由于传入的name参数与name变量更靠近,编译器会认为我们使用的是传入的name参数,而不是更远的类成员name。