c++访问控制和继承
通常认为一个类有2种不同的用户:普通用户和类的实现者。普通用户编写的代码使用类的对象,这部分代码只能访问类的公有成员;实现者则负责写类的成员和友元代码,成员和友元既能访问类的公有部分,也能访问类的私有部分。如果进一步考虑继承的话就会出现第3种用户,即派生类。派生类可以访问基类的公有(public)成员和受保护(protected)成员,但不能访问基类的私有(private)成员。
1、派生类不能访问基类的私有(private)成员
class Father {
private:
int money;
public:
void it_skill(void)
{
cout<<"father's it skill"<<endl;
}
int getMoney(void)
{
return money;
}
void setMoney(int money)
{
this->money = money;
}
};
class Son : public Father {
private:
int toy;
public:
void play_game(void)
{
int m;
cout<<"son paly game"<<endl;
/* money -= 1;
* 错: 派生类不能访问基类的私有(private)成员
*/
m = getMoney();
m--;
setMoney(m);
}
};
int main(int argc, char **argv)
{
Son s;
s.setMoney(10);
cout << s.getMoney()<<endl;
s.it_skill();
s.play_game();
return 0;
}
2、派生类可以访问基类的保护成员,类的对象则不行
class Father {
private:
int money;
protected:
int room_key;
public:
void it_skill(void)
{
cout<<"father's it skill"<<endl;
}
int getMoney(void)
{
return money;
}
void setMoney(int money)
{
this->money = money;
}
};
class Son : public Father {
private:
int toy;
public:
void play_game(void)
{
int m;
cout<<"son paly game"<<endl;
/* money -= 1;
* 错: 派生类不能访问基类的私有(private)成员
*/
m = getMoney();
m--;
setMoney(m);
room_key = 1; /* 派生类可以访问基类的保护成员 */
}
};
int main(int argc, char **argv)
{
Son s;
s.setMoney(10);
cout << s.getMoney()<<endl;
s.it_skill();
s.play_game();
//s.room_key = 1; 类的对象不能访问保护成员
return 0;
}
3、派生类可以修改基类的权限
派生类可以修改基类的权限,前提是派生类可以访问到基类的成员,即派生类不能修改基类的private成员,因为派生类不能访问基类的private成员。
class Son : public Father {
private:
int toy;
public:
using Father::room_key;/* 派生类修改基类成员的权限为public,类的对象可以访问 */
//using Father::money;/* 派生类不能修改基类的private成员,因为派生类不能访问基类的private成员 */
void play_game(void)
{
int m;
cout<<"son paly game"<<endl;
/* money -= 1;
* 错: 派生类不能访问基类的private成员
*/
m = getMoney();
m--;
setMoney(m);
room_key = 1;
}
};
int main(int argc, char **argv)
{
Son s;
s.setMoney(10);
cout << s.getMoney()<<endl;
s.it_skill();
s.play_game();
s.room_key = 1; /* 由于派生类将基类的protected成员改为public权限,故可以访问 */
return 0;
}
4、private,protected,public继承的区别
无论是哪种继承方式,在派生类内部使用父类时并无差别,即无论什么方式继承,派生类可以访问基类的protected和public成员。不同的继承方式,会影响这两方面:外部代码对派生类的使用、派生类的子类。
class Father {
private:
int money;
protected:
int room_key;
public:
int address;
void it_skill(void)
{
cout<<"father's it skill"<<endl;
}
};
class Son_pub : public Father {
private:
int toy;
public:
void play_game(void)
{
room_key = 1; // **无论是哪种继承方式,在派生类内部使用父类时并无差别**
}
};
class Son_pro : protected Father {
private:
int toy;
public:
void play_game(void)
{
room_key = 1; // **无论是哪种继承方式,在派生类内部使用父类时并无差别**
}
};
class Son_pri : private Father {
private:
int toy;
public:
void play_game(void)
{
room_key = 1; // **无论是哪种继承方式,在派生类内部使用父类时并无差别**
}
};
int main(int argc, char **argv)
{
Son_pub s_pub;
Son_pro s_pro;
Son_pri s_pri;
s_pub.play_game();
s_pro.play_game();
s_pri.play_game();
s_pub.it_skill();
//s_pro.it_skill(); // 错误,protected继承,使用则不能访问protected成员
//s_pri.it_skill(); // 错误,private继承,使用则不能访问private成员
return 0;
}
5、覆写
派生类实现基类相同的函数,在使用时会调用派生类的函数,不会调用基类的函数。
class Father {
private:
int money;
protected:
int room_key;
public:
void it_skill(void)
{
cout<<"father's it skill"<<endl;
}
};
class Son : public Father {
private:
int toy;
public:
using Father::room_key;
/* 覆写 override */
void it_skill(void)
{
cout<<"son's it skill"<<endl;
}
};
int main(int argc, char **argv)
{
Son s;
s.it_skill();//调用派生类的it_skill
return 0;
}
6、派生类到基类的类型转换
一个派生类的对象中,包含继承自基类的部分和派生类自定义的部分。正因为派生类含有基类部分,所以可以进行派生类到基类的类型转换,这种转换是隐式的。不存在从基类向派生类的隐式类型转换。
派生类向基类的自动类型转换只对指针或引用有效,对象之间不存在类型转换。
class Person {
private:
char *name;
int age;
public:
void printInfo(void)
{
cout<<"father's printInfo"<<endl;
}
};
class Student : public Person {
private:
int grade;
public:
void printInfo(void)
{
cout<<"Student ";
Person::printInfo();
}
};
void test_func(Person &p)//传入的参数为基类的引用
{
p.printInfo();
}
int main(int argc, char **argv)
{
Person p;
Student s;
test_func(p);
test_func(s); /* Person &p = s里面的Person部分; 发生隐式转换
* p引用的是"s里面的Person部分"
*/
s.printInfo();
return 0;
}