您的位置:首页 > 编程语言 > C语言/C++

C++的访问控制符与多态之间的关系

2016-01-20 21:40 501 查看
本文将着重讨论C++的访问控制符(private、protected、public)与多态行为之间的关系。

访问控制符主要用于限制类成员的访问权限和限制类与类之间的继承关系(私有继承、保护继承、公有继承),按访问级别的不同,我们来对访问控制符从大到小排个序:

public>protected>private

多态行为的产生也需要有几个条件:

1)基类有虚函数或纯虚函数

2)存在继承,并且派生类override(覆盖)了基类了虚函数或纯虚函数

3)通过基类的指针或引用调用虚函数

这三者缺一不可,貌似多态和访问控制符没有什么关系,那么到底有没有关系呢?

接下来我们分几种情况来讨论这个问题:

1、公有继承

特点:在派生类中,基类所有可访问数据成员(public、protected)的默认访问权限不发生变化:基类的公有数据成员在派生类中的访问权限还是公有的;基类的保护数据成员在派生类中的访问权限还是保护的;基类的私有数据成员在派生类中是不可被访问的;但是函数成员的访问权限可由派生类指定,不论指定为何种访问权限,都不影响多态的发生,详见下面的代码:

#include <iostream>

using namespace std;

class Base
{
public:
Base():ID1(0),ID2(0),ID3(0){}
virtual ~Base(){}
int ID1;
virtual void print1()=0;
protected:
int ID2;
virtual void print2()=0;
private:
int ID3;
virtual void print3()=0;
};

class Sub1:public Base
{
public:
Sub1(){}
virtual ~Sub1(){}
virtual void print1()
{
cout<<"print1,I'm sub1!"<<endl;
}
virtual void print2()
{
cout<<"print2,I'm sub1!"<<endl;
}
virtual void print3()
{
cout<<"print3,I'm sub1!"<<endl;
}
};

class Sub2:public Base
{
public:
Sub2(){}
virtual ~Sub2(){}
protected:
virtual void print1()
{
cout<<"print1,I'm sub2!"<<endl;
}
virtual void print2()
{
cout<<"print2,I'm sub2!"<<endl;
}
virtual void print3()
{
cout<<"print3,I'm sub2!"<<endl;
}
};

class Sub3:private Base
{
public:
Sub3(){}
virtual ~Sub3(){}
private:
virtual void print1()
{
cout<<"print1,I'm sub3!"<<endl;
}
virtual void print2() {
cout<<"print2,I'm sub3!"<<endl;
}
virtual void print3() {
cout<<"print3,I'm sub3!"<<endl;
}
};

int main(int argc,char *argv[])
{
Sub1 sub1;
Sub2 sub2;
Sub3 sub3;

Base *pb=(Base*)&sub1;
pb->print1();
sub1.print1();
sub1.print2();
sub1.print3();
cout<<endl;

pb=(Base*)&sub2;
pb->print1();
cout<<endl;

pb=(Base*)&sub3;
pb->print1();
cout<<endl;

return 0;
}


//编译、运行,上面的代码能输出:print1,I'm sub1!//通过基类指针调用</span>

print1,I'm sub1!//通过sub1实例调用

print2,I'm sub1!

print3,I'm sub1!

priint1, I'm sub2! //通过基类指针调用

print1,I'm sub3!//通过基类指针调用

成员访问权限:

1)、不可访问数据成员ID3在派生类中依然不可访问,可访问数据员在派生类中的访问权限均未发生变化;

2)、成员函数访问权限在派生类中可以修改为private、protected、public之中的任何一个,并且不影响多态行为

2、保护继承

特点:在派生类中,基类所有可访问数据成员(public、protected)的默认访问权限均为保护的,即:基类的公有数据成员在派生类中的访问权限是保护的;基类的保护数据成员在派生类中的访问权限是保护的;基类的私有成员在派生类中是不可被访问的;但是函数成员的访问权限可由派生类指定,不论指定为何种访问权限,都不影响多态的发生,详见下面的代码:

#include <iostream>

using namespace std;

class Base
{
public:
Base():ID1(0),ID2(0),ID3(0){}
virtual ~Base(){}
int ID1;
virtual void print1()=0;
protected:
int ID2;
virtual void print2()=0;
private:
int ID3;
virtual void print3()=0;
};

class Sub1:protected Base
{
public:
Sub1(){}
virtual ~Sub1(){}
virtual void print1()
{
cout<<"print1,I'm sub1!"<<endl;
}
virtual void print2()
{
cout<<"print2,I'm sub1!"<<endl;
}
virtual void print3()
{
cout<<"print3,I'm sub1!"<<endl;
}
};

class Sub2:protected Base
{
public:
Sub2(){}
virtual ~Sub2(){}
protected:
virtual void print1()
{
cout<<"print1,I'm sub2!"<<endl;
}
virtual void print2()
{
cout<<"print2,I'm sub2!"<<endl;
}
virtual void print3()
{
cout<<"print3,I'm sub2!"<<endl;
}
};

class Sub3:protected Base
{
public:
Sub3(){}
virtual ~Sub3(){}
private:
virtual void print1()
{
cout<<"print1,I'm sub3!"<<endl;
}
virtual void print2() {
cout<<"print2,I'm sub3!"<<endl;
}
virtual void print3() {
cout<<"print3,I'm sub3!"<<endl;
}
};

int main(int argc,char *argv[])
{
Sub1 sub1;
Sub2 sub2;
Sub3 sub3;

Base *pb=(Base*)&sub1;
pb->print1();
sub1.print1();
sub1.print2();
sub1.print3();
cout<<endl;

pb=(Base*)&sub2;
pb->print1();
cout<<endl;

pb=(Base*)&sub3;
pb->print1();
cout<<endl;

return 0;
}


//编译运行上面的代码,一样能产生多态行为并且与上面的输出结果一致;

成员访问权限:

1)、不可访问数据成员ID3在派生类中依然不可访问,可访问数据员在派生类中的访问权限发生了变化:public->protected,protected和private未发生变化

2)、成员函数访问权限在派生类中可以修改为private、protected、public之中的任何一个,并且不影响多态行为;

3、私有继承

特点:在派生类中,基类所有可访问数据成员(public、protected)的默认访问权限均为私有的,即:基类的公有数据成员在派生类中的访问权限是私有的;基类的保护数据成员在派生类中的访问权限是私有的;基类的私有成员在派生类中是不可被访问的;但是函数成员的访问权限可由派生类指定,不论指定为何种访问权限,都不影响多态的发生,详见下面的代码:

#include <iostream>

using namespace std;

class Base
{
public:
Base():ID1(0),ID2(0),ID3(0){}
virtual ~Base(){}
int ID1;
virtual void print1()=0;
protected:
int ID2;
virtual void print2()=0;
private:
int ID3;
virtual void print3()=0;
};

class Sub1:private Base
{
public:
Sub1(){}
virtual ~Sub1(){}
virtual void print1()
{
cout<<"print1,I'm sub1!"<<endl;
}
virtual void print2()
{
cout<<"print2,I'm sub1!"<<endl;
}
virtual void print3()
{
cout<<"print3,I'm sub1!"<<endl;
}
};

class Sub2:private Base
{
public:
Sub2(){}
virtual ~Sub2(){}
protected:
virtual void print1()
{
cout<<"print1,I'm sub2!"<<endl;
}
virtual void print2()
{
cout<<"print2,I'm sub2!"<<endl;
}
virtual void print3()
{
cout<<"print3,I'm sub2!"<<endl;
}
};

class Sub3:private Base
{
public:
Sub3(){}
virtual ~Sub3(){}
private:
virtual void print1()
{
cout<<"print1,I'm sub3!"<<endl;
}
virtual void print2() {
cout<<"print2,I'm sub3!"<<endl;
}
virtual void print3() {
cout<<"print3,I'm sub3!"<<endl;
}
};

int main(int argc,char *argv[])
{
Sub1 sub1;
Sub2 sub2;
Sub3 sub3;

Base *pb=(Base*)&sub1;
pb->print1();
sub1.print1();
sub1.print2();
sub1.print3();
cout<<endl;

pb=(Base*)&sub2;
pb->print1();
cout<<endl;

pb=(Base*)&sub3;
pb->print1();
cout<<endl;

return 0;
}



//编译运行上面的代码,一样能产生多态行为并且与上面的输出结果一致;


成员访问权限:

1)、不可访问数据成员ID3在派生类中依然不可访问,可访问数据员在派生类中的访问权限均变成了private;

2)、成员函数访问权限在派生类中可以修改为private、protected、public之中的任何一个,并且不影响多态行为;

结论:

1、继承方式(private、protected、public)影响数据成员的访问权限

2、继承方式(private、protected、public)不会影响多态行为的发生

3、在派生类中修改函数成员的访问控制符也不会影响多态行为的发生
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: