📄 c++10.dat
字号:
第五节 CONST 成员函数
一些成员函数改变对象,一些成员函数不改变对象.
例如:
int Point::GetY()
{
return yVal;
}
这个函数被调用时,不改变Point对象,而下面的函数改变Point对象:
void Point:: SetPt (int x, int y)
{
xVal=x;
yVal=y;
}
为了使成员函数的意义更加清楚,我们可在不改变对象的成员函数的函数原型中加上const说明:
例
class Point
{
public:
int GetX() const;
int GetY() const;
void SetPt (int, int);
void OffsetPt (int, int);
private:
int xVal, yVal;
};
const成员函数应该在函数原型说明和函数定义中都增加const限定:
例
int Point::GetY() const
{
return yVal;
}
class Set {
public:
Set (void){ card = 0; }
bool Member(const int) const;
void AddElem(const int);
//...
};
bool Set::Member (const int elem) const
{
//...
}
非常量成员函数不能被常量成员对象调用,因为它可能企图修改常量的数据成员:
const Set s;
s.AddElem(10); // 非法: AddElem不是常量成员函数
s.Member(10); // 正确
但构造函数和析构函数对这个规则例外,它们从不定义为常量成员,但可被常量对象调用(被自动调用).它们也能给常量的数据成员赋值,除非数据成员本身是常量.
第六节 静态成员
前面我们已经看到:每一个类对象有其公有或私有的数据成员,每一个public或private函数可以访问其数据成员.
有时,可能需要一个或多个公共的数据成员,能够被类的所有对象共享.在C++中,我们可以定义静态(static)的数据成员和成员函数.
6.1 静态数据成员
要定义静态数据成员,只要在数据成员的定义前增加static关键字.静态数据成员不同于非静态的数据成员,一个类的静态数据成员仅创建和初始化一次,且在程序开始执行的时候创建,然后被该类的所有对象共享;而非静态的数据成员则随着对象的创建而多次创建和初始化.
下面是静态数据成员定义的实例:
例
class Test
{
public:
static int public_int;
private:
static int private_int;
};
void main()
{
Test::public_int = 145; // 正确
Test::private_int = 12; // 错误,不能访问私有的数据成员
}
从上例我们可以看到:静态数据成员的访问方式是:
类名::静态数据成员名
但是,不能直接访问私有的数据成员.其实,上面的程序段只是为了介绍如何访问静态数据成员,不能通过编译器的的编译和连接.
一、私有的静态数据成员
为了说明私有的静态数据成员的使用,考虑下面的程序段:
class Directory
{
public:
...
private:
// 数据成员
static char path[];
};
数据成员path[]是一个私有的静态变量,在程序执行过程中,仅一个Directory::path[]存在,即使有多个Directory类的对象.静态的数据成员能够被类的成员函数访问,但不能在构造函数中初始化.这是因为静态数据成员在构造函数被调用之前就已经存在了.静态数据成员可以在定义时初始化,且必须在类和所有的成员函数之外,与全局变量初始化的方法一样.例如,类Directory的数据成员的定义与初始化方法如下:
// 静态数据成员的定义与初始化
char Directory::path [200] = "/usr/local";
// 无参的构造函数
Directory::Directory()
{
...
}
在类中的静态数据成员的定义,只是说明该类有这么一个数据成员,并没有为该数据成员分配内存.就象非静态数据成员是在创建对象时分配内存一样,静态数据成员是在初始化时分配内存的.所以,在定义静态的数组成员时,可以省略它的尺寸(数组元素的个数),但在初始化时,必须确定数组的尺寸.
6.2 静态成员函数
除静态数据成员外,C++也允许定义static成员函数.静态的数据成员被所有的对象共享,也就是说,静态数据成员不属于对象,而是属于类的.与静态数据成员类似,静态成员函数也是属于类的.
注意:静态成员函数仅能访问静态的数据成员,不能访问非静态的数据成员,也不能访问非静态的成员函数,这是由于静态的成员函数没有this指针.类似于静态的数据成员,公有的、静态的成员函数在类外的调用方式为:
类名::成员函数名(实参表)
不过,也允许用对象调用静态的成员函数.
下面举一个例子说明静态成员函数的调用方法:
例
class Directory
{
public:
...
// 静态公有的函数
static void setpath(char const *newpath);
private:
// 静态字符串
static char path [];
};
//静态数据成员的初始化
char Directory::path [199] = "/usr/local";
// 静态函数
void Directory::setpath(char const *newpath)
{
strncpy(path, newpath, 199);
}
// 使用实例
void main()
{
// 通过类名调用setpath()成员函数
Directory::setpath("/etc");
//通过象调用setpath()成员函数
Directory dir;
dir.setpath("/etc");
}
在上面的例子中, setpath()始一个公有静态的成员函数,C++也允许私有静态的成员函数,它只能被该类的其它成员函数调用,不能在类外被调用.
需要注意的是:静态的成员函数仅能访问静态的变量和静态的成员函数,不能访问非静态的数据成员和非静态的成员函数.
第七节 友元
类的主要特点是数据隐藏,即类的私有部分在该类的作用域之外是不可见的.但是,有时候可能需要在类的外部访问类的私有部分.为此,C++提供了一种方法,允许类外部的函数或者类具有该类的私有部分的特权,它通过关键字friend把其它类或非成员函数声明为一个类的“友元”.在类的内部,友元被作为该类的成员看待,并且对对象公用部分的访问没有任何限制.
友元函数的声明方式为:
class 类名称
{
type vars;
...
public:
friend 函数类型 函数名称(); //友元函数
...
};
例如,下面的程序段中定义了类Friend_Class及一个友元函数Friend_Function.
class Friend_Class //类Friend_Class的定义
{
private:
int nMemberData;
public:
//声明函数Friend_Function为类Friend_Class的友元
friend void Friend_Function(Friend_Class class_member,int x);
};
//下面是友元函数Friend_Function的函数体,它要在类的外部定义
void Friend_Function(Friend_Class class_member,int x)
{
class_member.nMemberData=x; //通过友元函数访问类的私有成员
}
上面的程序中声明的友元函数Friend_Function并不是类Friend_Class的成员函数,而是一个普通的函数,不过由于它在类Friend_Class的定义中被声明为友元函数,因此,函数Friend_Function可以访问类Friend_Class的私有部分.函数在实际操作时,是通过传递给它的类Friend_Class的对象class_member进行对类的私有部分的访问.
注意,友元函数的定义与成员函数的定义是不一样的,它与普通函数的定义形式基本相同.在它的前面没有类名和作用域运算符“::”.
类的友元可以是一个函数,也可以是一个类.例如,下面的程序中将整个教师类看成是学生类的友元:
class Student;
class Teacher
{
public:
void assignGrades(Student &s);
void adjustHours(Student &s);
...
protected:
int noOfStudent;
Student *pList[100];
};
class Student
{
public:
friend class Teacher; //友元类
...
protected:
int semesterHours;
float gpa;
};
上面程序中,友元类是Teachder.C++中规定,友元类必须在它被定义以前声明.因此,上面的例子中,类Teacher定义在类Student之前.一旦一个类被声明为另一个类的友元函数之后,该类的每一个成员函数都是另一个类的友元函数.一个类的友元的声明既可以在该类定义的公用部分声明,也可以在类的私有部分声明.两个类还可以相互定义为对方的友元,当两个类的联系较紧密时,把它们定义为相互的友元就更为有意义了.
尽管使用友元函数可以访问类中的私有数据,但为了确保数据的完整性及数据封装与隐藏的原则,建议尽量少用或不用友元函数.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -