一、修饰符public/protect/private
1.修饰谁
C++提供了三种类成员访问修饰符public(公共)、protected(保护)、private(私有)。
可以修饰用于两个地方:
- 成员前。对于该成员受访范围进行限制。
- 父类前。对于父类成员能否被继承以及继承成何种成员进行限制。
2.有什么作用
(1)对受访范围的影响
- 在private下的成员,对于整个类都是可见的,对于友元函数是可见的,对于派生类(子类)是不可见的,对于类的外部是不可见的。
- 在protected下的成员,对于整个类都是可见的,对于友元函数是可见的,对于派生类(子类)是可见的,对于类的外部是不可见的。
- 在public下的成员,任何情况都是可见的。
如果没有修饰符,缺省情况是private。
(2)对继承的影响
继承为子类public? | 继承为子类protected? | 继承为子类private? | |
---|---|---|---|
父类public中的成员 | public继承:Yes | protected继承:Yes | private继承:Yes |
父类protected中的成员 | public继承:Yes protected继承:Yes | private继承:Yes | |
父类private中的成员 | private成员不能被继承 | private成员不能被继承 | private成员不能被继承 |
总结:父类private中的成员不会被子类继承,父类public和protected中的成员,结合继承时父类的成员访问修饰符,访问范围两者中取小。
#include<iostream.h>
class Base
{
public:
int b_public_x;
void b_public_fun()
{
b_public_x = 1;
cout << "Base public fun" << endl;
}
protected:
int b_protected_x;
void b_protected_fun()
{
b_protected_x = 1;
cout << "Base protected fun" << endl;
}
private:
int b_private_x;
void b_private_fun()
{
b_private_x = 1;
cout << "Base private fun" << endl;
}
};
class Public_Derived : public Base {
public:
void p_d_public_fun(){
b_public_x = 2;
b_protected_x = 2;
//b_private_x = 2; //wrong,private成员不能被继承
b_public_fun();
b_protected_fun();
//b_private_fun();//wrong,private成员不能被继承
}
};
class Protected_Derived : protected Base {
public:
void p_d_public_fun(){
b_public_x = 2;
b_protected_x = 2;
//b_private_x = 2; //wrong,private成员不能被继承
b_public_fun();
b_protected_fun();
//b_private_fun();//wrong,private成员不能被继承
}
};
class Private_Derived : private Base {
public:
void p_d_public_fun(){
b_public_x = 2;
b_protected_x = 2;
//b_private_x = 2; //wrong,private成员不能被继承
b_public_fun();
b_protected_fun();
//b_private_fun();//wrong,private成员不能被继承
}
};
class Public_DDerived : public Public_Derived {
public:
void p_dd_public_fun(){
b_public_x = 2;
b_protected_x = 2;
b_public_fun();
b_protected_fun();
}
};
class Protected_DDerived : protected Public_Derived {
public:
void p_dd_public_fun(){
b_public_x = 2;
b_protected_x = 2;
b_public_fun();
b_protected_fun();
}
};
class Private_DDerived : private Public_Derived {
public:
void p_dd_public_fun(){
b_public_x = 2;
b_protected_x = 2;
b_public_fun();
b_protected_fun();
}
};
int main()
{
Base obj;
obj.b_public_x = 0;
//obj.b_protected_x = 0;//wrong,protected成员不能在类外被访问
//obj.b_private_x = 0;//wrong,private成员不能在类外被访问
obj.b_public_fun();
//obj.b_protected_fun();//wrong,protected成员不能在类外被访问
//obj.b_private_fun();//wrong,private成员不能在类外被访问
Public_Derived obj1;
obj1.b_public_x = 2;
//obj1.b_protected_x = 2;//wrong,protected成员不能在类外被访问
obj1.b_public_fun();
//obj1.b_protected_fun();//wrong,protected成员不能在类外被访问
Protected_Derived obj2;
//obj2.b_public_x = 2;//wrong,protected成员不能在类外被访问
//obj2.b_protected_x = 2;//wrong,protected成员不能在类外被访问
//obj2.b_public_fun();//wrong,protected成员不能在类外被访问
//obj2.b_protected_fun();//wrong,protected成员不能在类外被访问
Private_Derived obj3;
//obj3.b_public_x = 2;//wrong,private成员不能在类外被访问
//obj3.b_protected_x = 2;//wrong,private成员不能在类外被访问
//obj3.b_public_fun();//wrong,private成员不能在类外被访问
//obj3.b_protected_fun();//wrong,private成员不能在类外被访问
return 0;
}
二、修饰符friend
通常对于普通函数来说,要访问类的保护和私有成员是不可能的。如果想这么做,那么必须把类的成员都设置为public,然而这样带来的问题就是任何外部函数都可以访问它。C++提供friend修饰符,可以让一些你设定的函数能够访问保护和私有成员,避免把类成员全部设置成public,最大限度地保护数据成员的安全。
friend可以修饰用于两个地方:
(1)函数前。在类内声明某个普通函数是本类的友元函数。一个普通函数可以是多个类的友元函数。一个类的成员函数函数也可以是另一个类的友元。
#include <iostream>
using namespace std;
class Base
{
public:
Base(char *name)
{
strcpy(Base::name,name);
}
friend void ShowN(Base &obj);//友元函数的声明
public:
char name[20];
};
void ShowN(Base &obj)//友元函数的定义
{
cout<<obj.name<<endl;
}
void main()
{
Base a="zjgsu";
ShowN(a);
}
(2)类前。整个类是另一个类的友元,该友元可以称为友元类或友类。友类的每个成员函数都可以访问另一个类的所有成员。
下例中,Base是Country的友元类。
#include <iostream>
using namespace std;
class Country
{
public:
Country()
{
strcpy(cname,"中国");
}
friend class Base;//友类的声明
private:
char cname[30];
};
class Base //友类的定义
{
public:
Base(char *name)
{
strcpy(Base::name,name);
}
void ShowN(Country &temp);
private:
char name[20];
};
void Base::ShowN(Country &temp)
{
strcpy(temp.cname,"中华人民共和国");
cout<<name<<endl;
}
void main()
{
Base a="zjgsu";
Country b;
a.ShowN(b);
}
另外,注意几点:
- 友元关系不可传递。如果A是B的友元,B是C的友元,不代表A是C的友元。
- 友元关系不能被继承。也就是说父类中的友元不能访问子类私有和保护成员。
- 友元关系具有单向性。如果A是B的友元,不代表B是A的友元。