一、protected
· 访问范围: 公有成员>保护成员>私有成员
· 表现形式: 能访问私有成员的方式都能访问保护成员,基类的保护成员可以在派生类的成员函数中被访问
//基类
class Student {
string name;
protected:
int ID;
void ShowName() { cout << "Name\t" << Student::name << endl; }
public:
Student(string n, int id) :name(n), ID(id) {}
};
//派生类
class Person :public Student {
public:
Person(string n, int id):Student(n, id) {}
void show() {
//cout << "Name\t" << Student::name << endl;//错误 name是私有成员
ShowName();
cout << "ID\t" << Student::ID << endl;
}
};
二、static
1. 静态成员变量
· 必须在类外使用 数据类型 类名::静态变量名; 定义
· 若定义在类的public域,类外可以访问它
2. 静态成员函数
· 静态成员函数只能访问静态成员变量
class MyClass{
int x;
static int y;
public:
static int z;
void show(){
cout<<"x\t"<<x<<endl;
//非静态成员函数可以访问静态成员变量
cout<<"y\t"<<y<<endl;
cout<<"z\t"<<z<<endl;
}
static void s_show(){
//cout<<"x\t"<<x<<endl;//错误 静态成员函数不能访问非静态成员变量
cout<<"y\t"<<y<<endl;
cout<<"z\t"<<z<<endl;
}
MyClass(int x,int y,int z):x(x)/*,y(y) 错误 y 不是 MyClass 的非静态数据成员或基类*/
{this->y=y; this->z=z;}//正确
};
//int MyClass::x;//错误 非静态数据成员不能在其类的外部定义
int MyClass::y;
int MyClass::z;
三、成员指针
1. 成员变量的指针
· 定义: 数据类型*指针名=&对象名.成员变量名;
2. 成员函数的指针
· 定义: 返回值类型 (类名:: * 指针名)(形参);
· 使用成员函数的指针前,须先创建对象
class Point {
int X, Y;
public:
int n;
void Set_XY(int x, int y) { X = x; Y = y; }
void display() { cout << "X=" << X << ",Y=" << Y << endl; }
};
void main() {
//成员函数指针的定义
void (Point:: * p2)(int, int);
p2 = &Point::Set_XY;
void (Point:: * p3)() = &Point::display;
//未创建对象 不能使用
Point c;
Point* p1 = &c; //对象指针
p1->Set_XY(1, 1); //使用指针调用成员函数
int* pn = &c.n; //使用成员变量指针访问成员变量
*pn = 10;
(c.*p3)(); //使用成员函数指针调用成员函数display
(c.*p2)(2, 3); //使用成员函数指针调用成员函数Set_XY
(c.*p3)();
system("pause");
};
四、const
1. 常对象
· 定义: const 类名 对象名;
· 不能修改非static成员变量
· 不能调用非static/const成员函数,防止修改数据
2. 常成员函数
· 定义: 返回值类型 函数名(形参) const{}
· 不能修改非static成员变量
· 可以访问该类的所有成员变量
3. 常成员变量
· 用法与一般常变量一样
class MyClass {
public:
int x;
static int y;
const int z;
void show() {}
static void s_show() {
//cout<<"x\t"<<x<<endl;//错误 静态成员函数不能访问非静态成员变量
cout << "y\t" << y << endl;
cout << "z\t" << z << endl;
}
void c_show() const {
//x++; //错误 不可修改非static成员变量
y++;
cout << "x\t" << x << endl;
cout << "y\t" << y << endl;
cout << "z\t" << z << endl;
}
MyClass(int x = 1, int y = 2, int z = 3) :x(x)/*,y(y) 错误*/,z(z)
{ this->y = y; /*this->z = z; 错误 应使用构造函数初始化表*/ }
};
int MyClass::y;//静态数据成员必须在其类的外部定义
void main(){
const MyClass A;
//MyClass const A //与上一条语句等价
//A.x++; //错误 常对象不能修改非static成员变量
A.y++; //正确
//A.show(); //错误 常对象不能调用非static/const成员函数
A.s_show(); //正确
A.c_show();
}
五、友元
1. 友元函数
· 声明: friend 返回值类型 函数名(形参);
· 友元函数不是该类的成员函数
· 友元函数可以访问该类的私有成员
class Point {
int x, y;
public:
Point(int xx = 0, int yy = 0) :x(xx), y(yy) {}
int GetX() { return x; }
int GetY() { return y; }
friend double Distance(Point& a, Point& b); //须在类中声明它的友元
};
double Distance(Point& a, Point& b) {
double dx = a.x - b.x;
double dy = a.y - b.y;
return sqrt(dx * dx + dy * dy);
}
2. 友元类
· 声明: friend class 类名;
· 如果B是A的友元类,则B类的所有成员函数都可访问A类的私有成员
class A {
int x;
void Display() { cout << x << endl; }
friend class B;
};
class B{
A a;
public:
void Set(int i) { a.x = i; }
void Display() { a.Display();}
};
//去掉内嵌对象a,修改两个成员函数
class A {
static int x;
static void Display() { cout << x << endl; }
friend class B;
};
class B {
public:
void Set(int i) { A::x = i; }
void Display() { A::Display(); }
};
六、关于报错: 非静态成员的引用必须与特定对象相对
原因: 类的成员分为实例成员和静态成员,他们的储存空间不同
实例成员: 储存空间属于具体的实例(对象),不同实例名下的成员有不同的储存空间
访问实例成员
不能用 ClassName::MemberName
只能用 Object.MemberName
静态成员: 储存空间是固定的,与具体的实例无关,被该类的所有对象共享
访问静态成员
可以用 ClassName::MemberName
也可以用 Object.MemberName