[C++]访问控制与继承(public,protect,private)
C++有三种访问控制符号:public,protect,private,
同时,也有三种继承方式:public,protect,private。
访问控制
访问控制是对类成员而言的,对非类成员而言,访问控制是不适用的。
在Java,C#中,也有访问控制的概念,不过Java和C#中,访问控制的用法与C++不用:
class Foo
{ // C++支持这种形式
public:
int a;
};
class Foo
{ // C#支持这种形式
public int a;
}
public
木有任何限制
private
只能被类声明中的成员函数和友元访问。
注意~这里是“类声明中”而不是“实例中”,同一个类的不同实例,是可以互访private成员的,下文的protect也类似:
#include <iostream>
class Foo
{
private:
int _val;
public:
Foo(int val): _val(val){};
int GetValue(Foo& foo)
{ // 访问private成员
return foo._val;
}
};
int main(void)
{
Foo foo1(1);
Foo foo2(2);
std::cout << foo1.GetValue(foo1) << std::endl;
// foo1访问了foo2的private成员,跨实例访问
std::cout << foo1.GetValue(foo2) << std::endl;
}
private的另一个用途是禁用编译器自动生成的代码。对于一个类,编译器自动构造3个玩意:
默认构造函数、默认复制构造函数、默认赋值函数,如果不想让编译器生成这3个玩意,需要显式将之设置为private属性~:
#include <iostream>
class FooA
{
public:
int value;
};
int main(void)
{
using namespace std;
// 调用了编译器生成的默认构造函数
FooA fooA1;
fooA1.value = 5;
// 调用了编译器默认生成的复制构造函数
FooA fooA2 = fooA1;
fooA1.value = 10;
FooA fooA3;
// 调用了编译器默认生成的赋值函数
fooA3 = fooA1;
cout << fooA1.value << fooA2.value << fooA3.value << endl;
system("pause");
}
#include <iostream>
class FooB
{
public:
int value;
FooB(int v):value(v){};
// 通过private禁用了以下3个玩意
private:
FooB();
FooB(FooB&);
FooB& operator=(FooB&);
};
int main(void)
{
using namespace std;
// 禁用了默认构造函数:
// error C2248: “FooB::FooB”: 无法访问 private 成员(在“FooB”类中声明)
// FooB fooB1;
FooB fooB1(0);
fooB1.value = 5;
// 禁用了复制构造函数
// error C2248: “FooB::FooB”: 无法访问 private 成员(在“FooB”类中声明)
// FooB fooB2 = fooB1;
fooB1.value = 10;
FooB fooB3(0);
// 禁用了赋值运算符
// error C2248: “FooB::operator =”: 无法访问 private 成员(在“FooB”类中声明)
// fooB3 = fooB1;
//cout << fooB1.value << fooB2.value << fooB3.value << endl;
system("pause");
}
protect
如果不考虑继承,protect和private完全一样。但是在继承中,protect就有了各种奇葩的表现。
继承访问控制
在继承中,可以指定继承方式,继承方式和上述的访问控制相结合,用以派生类中基类成员的访问控制。
继承访问控制和基类成员的访问控制的结合,有如下规律——“从严控制”,显然,由宽松至严格的顺序为:
public>protect>private
public继承
最宽松的继承,基类成员的访问控制不变~
protect继承
基类的

浙公网安备 33010602011771号