关于private继承的几点理解
2014-09-16 21:52
225 查看
不论派生类以何种方式继承基类,派生类本身(非派生类对象,指成员函数等)都是能访问基类的public 和 protected成员。但若以private方式继承,则派生类的对象、指针、引用则不能访问基类的任何成员。
代码如下:
2)派生类本身是能访问基类的public 和protected成员的,如Dfun1函数访问了Bfun1 Dfun2函数访问了Bfun2;
二、关于《Effective c++》中Item 39
1、如果类之间的关系是private继承,则:a:编译器不会自动将一个派生类对象转换成一个基类对象 b: 基类中的所有成员在派生类中都编程private属性,派生类对象无法访问
2、private表现出的关系是“根据某物实现出”,它继承的是实现而非接口
乍看很奇怪,实现都继承了怎么接口都不继承。这样理解,我们派生类需要利用private 基类中的一些成员实现某些东西,但是成员经过继承后变成了private属性,用户是无法通过接口访问它的,所以只是继承了实现而忽略了接口。
3、private继承主要用于:当两个类不存在“is-a”的关系,其中一个需要访问另一个的protected成员,或需要重新定义一个或多个virtual函数
这句话这么理解:现有两个类并非“is-a”关系,类D需要用类B的一些成员去实现它,而且我要用到的这些成员往往是类B的protected成员或者是虚函数。但是我只是需要这些成员去实现我的类D,并不给用户提供接口能直接访问类B的这些成员,这时候就应该用private继承。
我们看一个例子吧,这是Item 40改编过来的。
我希望实现一个类CPerson 它能提取人的name 和 birthdate,我想偷个懒,发现有这么一个类PersonInfo能实现差不多的功能,只是Person的格式有点不符合我的要求,我就打算利用PersonInfo来实现我Cperson的name函数和birthdate函数。
我们发现:a:类CPerson的name通过调用类PersonInfo的成员函数实现,我这里用了它的实现,却没有给用户提供调用类PersonInfo成员的接口(因为是private继承)
b:由于PersonInfo的格式不符合我的要求,(它是用的方括号[ ],我却不想要方括号),而控制格式的是两个虚函数valueDelimOpen valueDelimClose 这里我就可以重定义virtual函数了,在Cperson中,我们重定义了上述两个控制格式的函数。 这就是上面说的“需要重新定义一个或多个virtual函数”的情况
4、
代码如下:
#include <iostream> using namespace std; class Base { public: void Bfun1(){cout << "I'm Bfun1()" << endl;} protected: void Bfun2(){cout << "I'm Bfun2()" << endl;} private: void Bfun3(){cout << "I'm Bfun3()" << endl;} }; class Derived : private Base { public: void Dfun1() {cout << "I'm Dfun1() " ;Bfun1();} void Dfun2() {cout << "I'm Dfun2() " ;Bfun2();} }; int main() { Derived d; d.Dfun1(); d.Dfun2(); //d.Bfun1(); //d.Bfun2(); // d.Bfun3(); return 0; }运行后我们可以发现:1)派生类对象d是无法访问基类的任一成员函数的(包括public成员函数),因为这是private继承
2)派生类本身是能访问基类的public 和protected成员的,如Dfun1函数访问了Bfun1 Dfun2函数访问了Bfun2;
二、关于《Effective c++》中Item 39
1、如果类之间的关系是private继承,则:a:编译器不会自动将一个派生类对象转换成一个基类对象 b: 基类中的所有成员在派生类中都编程private属性,派生类对象无法访问
2、private表现出的关系是“根据某物实现出”,它继承的是实现而非接口
乍看很奇怪,实现都继承了怎么接口都不继承。这样理解,我们派生类需要利用private 基类中的一些成员实现某些东西,但是成员经过继承后变成了private属性,用户是无法通过接口访问它的,所以只是继承了实现而忽略了接口。
3、private继承主要用于:当两个类不存在“is-a”的关系,其中一个需要访问另一个的protected成员,或需要重新定义一个或多个virtual函数
这句话这么理解:现有两个类并非“is-a”关系,类D需要用类B的一些成员去实现它,而且我要用到的这些成员往往是类B的protected成员或者是虚函数。但是我只是需要这些成员去实现我的类D,并不给用户提供接口能直接访问类B的这些成员,这时候就应该用private继承。
我们看一个例子吧,这是Item 40改编过来的。
我希望实现一个类CPerson 它能提取人的name 和 birthdate,我想偷个懒,发现有这么一个类PersonInfo能实现差不多的功能,只是Person的格式有点不符合我的要求,我就打算利用PersonInfo来实现我Cperson的name函数和birthdate函数。
class PersonInfo{ public: explicit PersonInfo(DatabaseID pid); virtual ~PersonInfo(); virtual const char* theName() const; virtual const char* theBirthDate() const; ... private: virtual const char* valueDelimOpen() const{return "["}; //“开始”符号,用于姓名的输出 virtual const char* valueDelimClose() const{return "]"}; //“结束”符号 ... }; const char* PersonInfo::theName() const{ static char value[Max_Formatted_Field_Value_Length]; //保留缓冲区给返回值使用。注意由于缓冲区是static的,会被自动初始化为“全部是0” std::strcpy(value, valueDelimOpen()); //写入起始符号 ... //添加姓名 std::strcat(value, valueDelimClose()); //写入结束符号 return value; } class CPerson : private PersonInfo{ public: std::string name()const {return PersonInfo::theName();} std::string birthDate()const {return PersonInfo::theBirthDate();} private: virtual const char* valueDelimOpen() const{return ""}; virtual const char* valueDelimClose() const{return ""}; ... };
我们发现:a:类CPerson的name通过调用类PersonInfo的成员函数实现,我这里用了它的实现,却没有给用户提供调用类PersonInfo成员的接口(因为是private继承)
b:由于PersonInfo的格式不符合我的要求,(它是用的方括号[ ],我却不想要方括号),而控制格式的是两个虚函数valueDelimOpen valueDelimClose 这里我就可以重定义virtual函数了,在Cperson中,我们重定义了上述两个控制格式的函数。 这就是上面说的“需要重新定义一个或多个virtual函数”的情况
4、
相关文章推荐
- 关于多重继承的一些理解
- 关于好多继承的问题,我们应该如何去理解
- (加精)关于面向对象的某些理解--- 抽象 继承
- 关于C++ 学习的几点 理解 之 c++关键字详解(volatile,mutable,explicit,dynamic_cast<T>(expression))等
- Android关于Service的几点理解
- 关于对继承和派生,进程和线程理解
- 关于C++的private继承问题
- 关于public, private 和 protected继承中对基类成员的访问
- 关于继承、派生、public、protected、private
- 关于DDS的几点理解
- 关于VC/MFC中内存管理、堆、堆栈概念理解收集的几点说明
- 关于关键字 extern static 的几点理解
- 关于职场成功的几点理解
- 关于mfc CSplitterWnd的几点理解
- [转]关于java继承的private关键字问题
- Java-关于子类是否继承了父类的private实例变量
- 关于封装,继承,多态三个概念的简单理解
- 关于JAVA中接口的几点理解
- 父进程和子进程关于数据和文件描述符的继承的理解
- 必须得说一下,子类关于从父类继承过来的private成员这点事儿