1.各类的private成员特性
public、private、protected继承只是影响到基类的public成员和protected成员。对于基类的private只有基类的成员可以访问。就算是限制最松的public继承,在派生类中的成员也不能访问基类的private成员,只能通过调用基类的非private接口来访问。所以基类的private成员和派生类的private成员在派生类中还是有区别的。如下:
class Base
{
public:
Base(int a):_a(a){}
void set_a(int a){_a=a;}
private:
int _a;
};
class Derived:public Base
{
public:
Derived(int a,int b):Base(a),_b(b){}
void derived_set_a(int a)
{_a=a;}
private:
int _b;
};
编译结果:: error C2248: '_a' : cannot access private member declared in class 'Base'
2.访问级别的改变规则
再次强调public、private、protected继承只是影响到基类的public成员和protected成员。
①如果是public继承,基类的public成员为派生类的public成员,基类的protected成员为派生类的protected成员。
②如果是pprotected继承,基类的public成员和protected成员在派生类中为protected成员。
③如果是private继承,基类的public成员和protected成员在派生类中为private成员。
注意这里private继承的时候,private的成员是可以访问基类中public和protected成员的。但是是在定义的接口中访问,不是对象直接访问。
class Base
{
public:
Base(int a):_a(a),protected_a(a){}
void set_a(int a){_a=a;}
protected:
int protected_a;
private:
int _a;
};
class Derived:private Base
{
public:
Derived(int a,int b):Base(a),_b(b){}
void print_protected_a(){cout << protected_a;}
private:
int _b;
};
这段程序是正确的!
那么protected继承和private继承的区别在哪里?关键在于派生类的派生类的访问权限不一样。如下面两段程序:
class CSample1 {
protected:
void printProtected() {}
public:
void printPublic() {}
};
class CSample2 : protected CSample1 {};
class CSample3 : public CSample2 {
void print3() {
printProtected();
printPublic();
}
};
class CSample1 {
protected:
void printProtected() {}
public:
void printPublic() {}
};
class CSample2 : private CSample1 {};
class CSample3 : public CSample2 {
void print3() {
printProtected(); // 编译错误,不可以调用该函数
printPublic(); // 编译错误,不可以调用该函数
}
};
3. using声明
如果进行private或protected继承,则基类成员的访问级别在派生类中比在基类中更受限:
class Base{
public:
std::size_t size() const {return n;}
protected:
std::size_t n;
}
class Derived : private Base{...};
在这一继承层次中,size在Base中为public,但在Derived中为private。为了使size在Derived中成为public,可以在Derived的public部分增加一个using声明。如下这样改变Derived的定义,可以使size成员能够被用户访问,并使n能够被从Derived派生的类访问:
class Derived : private Base{
public:
using Base::size;
privated:
using Base::n;
}
4.struct与class的区别
用struct和class保留字定义的类具有不同的默认访问级别。同样,默认继承访问级别根据使用哪个保留字定义派生类也不相同。使用class保留字定义的派生类默认具有private继承,而用struct保留字定义的类默认具有public继承:
class Base{/*...*/}
struct D1 : Base{/*...*/}; //public inheritance by default
class D2 : Base{/*...*/}; //private inheritance by default
有一种常见的误解认为用struct保留字定义的类与用class定义的类有更大的区别。实际上它们唯一的不同只是①默认的成员保护级别和②默认的派生保护级别,除此之外,再也没有其他的区别。
5.例题
下面程序标记为A至J的语句哪些是正确的哪些是错误的?
#include <iostream>
using namespace std;
class Parent
{
public:
Parent(int var = -1)
{
m_nPub = var;
m_nPtd = var;
m_nPrt = var;
}
public:
int m_nPub;
protected:
int m_nPtd;
private:
int m_nPrt;
};
class Child1:public Parent
{
public:
int GetPub(){return m_nPub;}
int GetPtd(){return m_nPtd;}
int GetPrt(){return m_nPrt;} //A
};
class Child2:protected Parent
{
public:
int GetPub(){return m_nPub;}
int GetPtd(){return m_nPtd;}
int GetPrt(){return m_nPrt;} //B
};
class Child3:private Parent
{
public:
int GetPub(){return m_nPub;}
int GetPtd(){return m_nPtd;}
int GetPrt(){return m_nPrt;} //C
};
int main()
{
Child1 cd1;
Child2 cd2;
Child3 cd3;
int nVal=0;
//public 继承
cd1.m_nPub=nVal;//D
cd1.m_nPtd=nVal;//E
nVal=cd1.GetPtd();//F
//protected 继承
cd2.m_nPub=nVal;//G
nVal=cd2.GetPtd();//H
//private 继承
cd3.m_nPub=nVal;//I
nVal=cd3.GetPtd();//J
return 0;
}
正确的是:DFHJ;错误的是:ABCEGI