类成员的访问权限:
私有成员(private):可以被类自身的成员和友元访问,但不能被包括派生类在内的其他任何类和任何普通函数访问
公有成员(public):可以被任何普通函数和任何类的成员函数访问
保护成员(protected):可以被类自身的成员和友元访问外,还可以被派生类的成员函数访问,但不能被任何非友元的普通函数访问
类的三种继承方式:
公有继承(public):
保护继承(protected):
私有继承(private):
公有继承
公有继承的特点:
(1) 基类的私有成员不能被派生类的函数成员访问
(2) 基类的公有成员和保护成员在派生类中的访问权限不变
分析例上面那例子
基类CLocation中的公有成员Getx()、Gety()和MoveTo(),在派生类CPoint中的访问权限仍然是公有的。
而x,y是基类CLocation的私有成员,在派生类CPoint的成员函数中不能访问。如果将CPoint类的成员函数Show()改写成下面的形式:
void CPoint::Show()
{
cout << x << "," << y << " " << Color << endl ;
}
若将基类CLocation中的x,y改成保护成员,即:
class CLocation
{
将x,y改为保护成员后,上面的show()就可以直接访问成员x和y了 |
int x;
int y;
public:
int Getx();
int Gety();
void MoveTo(int x, int y);
CLocation(int x=0, int y=0);
};
分析例1CPoint类的部分成员属性:
CPoint类的成员函数不能访问的成员有:
int x; //继承基类的私有成员,类的成员函数不可访问
int y; //继承基类的私有成员,类的成员函数不可访问
CPoint类的私有成员有:
char Color[10]; //自己定义的私有成员
CPoint类的公有成员有:
int Getx(); //继承基类的公有成员,仍然是公有成员
int Gety(); //继承基类的公有成员,仍然是公有成员
void MoveTo(int x, int y); //继承基类的公有成员,仍然是公有成员
void SetColor(char *c); //自己定义的公有成员
void Show(); //自己定义的公有成员
保护继承
保护继承的特点:
(1) 基类的私有成员不能被派生类的函数成员访问
(2) 基类的公有成员和保护成员在派生类中的访问权限变为保护类型
例7.2 将例1的继承方式改为保护继承,其他代码保持不变
class CPoint : protected CLocation
{
private:
char Color[10];
public:
CPoint(char *c);
void SetColor(char *c);
void Show();
};
改为保护继承后,主函数不变编译时,是否正确?
void main(void)
{
CPoint p("Red");
p.Show();
p.MoveTo(7,8); //错误:不能在主函数中访问CLocation类的函数MoveTo(),只能在派生类的成员函数中访问
p.Show();
p.SetColor("Green");
p.Show();
}
为实现点的移动,可在CPoint类中再添加一个公有成员函数MoveTo(),如下:
class CPoint:protected CLocation
{
private:
char Color[10];
public:
CPoint(char *c);
void SetColor(char *c);
void Show();
void MoveTo(int x, int y);
};
void CPoint::MoveTo(int x, int y)
{
CLocation::MoveTo(x,y);
}
标识符的作用范围:成员函数作用域(如函数内部定义的局部变量及函数参数),类或者派生类作用域(如类中定义的数据成员或成员函数),基类作用域(如基类中定义的数据成员或成员函数),全局作用域(如定义的全局变量,及全局函数,即普通函数)。
标识符的访问原则:如果在某一程序段中有一个以上的同名标识符都有效,则标识符的作用范围越小,被访问到的优先级越高。
如果希望访问作用范围更大的标识符,则可以用类名和作用域运算符进行限定。如: CLocation::MoveTo(x,y)。
分析本例CPoint类的部分成员属性:
CPoint类的成员函数不能访问的成员有:
int x; //继承基类的私有成员,类的成员函数不可访问
int y; //继承基类的私有成员,类的成员函数不可访问
CPoint类的私有成员有:
char Color[10]; //自己定义的私有成员
CPoint类的保护成员有:
int Getx(); //继承基类的公有成员,成为保护成员
int Gety(); //继承基类的公有成员,成为保护成员
void MoveTo(int x, int y); //继承基类的公有成员,成为保护成员
CPoint类的公有成员有:
void MoveTo(int x, int y); //自己定义的公有成员
void SetColor(char *c); //自己定义的公有成员
void Show(); //自己定义的公有成员
私有继承的特点:
(1) 基类的私有成员不能被派生类的函数成员访问
(2) 基类的公有成员和保护成员在派生类中的访问权限变为私有类型
将例1的继承方式改为私有继承,其他代码保持不变
class CPoint : private CLocation
{
private:
char Color[10];
public:
CPoint(char *c);
void SetColor(char *c);
void Show();
};
分析本例CPoint类的部分成员属性:
CPoint类的成员函数不能访问的成员有:
int x; //继承基类的私有成员,类的成员函数不可访问
int y; //继承基类的私有成员,类的成员函数不可访问
CPoint类的私有成员有:
char Color[10]; //自己定义的私有成员
int Getx(); //继承基类的公有成员,成为私有成员
int Gety(); //继承基类的公有成员,成为私有成员
void MoveTo(int x, int y); //继承基类的公有成员,成为私有成员
CPoint类的公有成员有:
void SetColor(char *c); //自己定义的公有成员
void Show(); //自己定义的公有成员
派生类继承基类成员访问权限的变化表:
派生控制
基类成员
|
private
|
protected
|
public
|
private
|
不能访问
|
不能访问
|
不能访问
|
protected
|
private
|
protected
|
protected
|
public
|
private
|
protected
|
public
|
例2 定义一个钟表类,数据成员有时、分、秒,成员函数包括设置时间和显示时间。再从钟表类派生出闹钟类,新增数据成员有响铃时间,成员函数包括响铃、显示响铃时间和设置响铃时间。
#include <iostream.h>
class Clock
{
public:
Clock(int h=0, int m=0, int s=0);
Clock(Clock &c);
void SetTime(int h, int m, int s);
void ShowTime();
private:
int Hour;
int Minute;
int Second;
};
Clock::Clock(int h, int m, int s) //构造函数的参数用于初始化时、分、秒
{
Hour = h;
Minute = m;
Second = s;
}
Clock::Clock(Clock &c) //拷贝构造函数将引用作为参数初始化新建对象
{
Hour = c.Hour;
Minute = c.Minute;
Second = c.Second;
}
void Clock::SetTime(int h, int m, int s) //设置时间
{
Hour = h;
Minute = m;
Second = s;
}
void Clock::ShowTime() //显示时间
{
cout << Hour << ":" << Minute << ":" << Second << endl;
}
class AlermClock : public Clock
{
private:
int AlermHour;
int AlermMinute;
int AlermSecond;
public:
AlermClock(int h=12, int m=0, int s=0);
void Alerm();
void SetAlermTime(int h, int m, int s);
void ShowAlermTime();
};
AlermClock::AlermClock(int h, int m, int s)
{
AlermHour = h;
AlermMinute = m;
AlermSecond = s;
}
void AlermClock::Alerm() // 转义字符‘\a’完成响铃
{
cout << "\a\a\a\a\a\a\a";
}
void AlermClock::SetAlermTime(int h, int m, int s)
{
AlermHour = h;
AlermMinute = m;
AlermSecond = s;
}
void AlermClock::ShowAlermTime()
{
cout << AlermHour << ":" << AlermMinute << ":" << AlermSecond << endl;
}
void main()
{
//构造函数采用缺省参数值,基类继承的数据成员初始化为(0,0,0),将AlermClock类自己定义的数据成员响铃时间置为(12,0,0) |
c.ShowTime();
c.ShowAlermTime();
c.SetTime(10,30,40);
c.SetAlermTime(6,30,0);
c.ShowTime();
c.ShowAlermTime();
c.Alerm();
}
程序运行结果为:
0 : 0 : 0
12 : 0 : 0
10 : 30 : 40
6 : 30 : 0
本文转载于唯C教育,【Linux基础】类的继承方式
http://www.weicedu.com/forum.php?mod=viewthread&tid=82&fromuid=4
(出处: http://www.weicedu.com/)
http://www.weicedu.com/forum.php?mod=viewthread&tid=82&fromuid=4
(出处: http://www.weicedu.com/)