设为首页 加入收藏

TOP

9.3.2 声明类的保护成员
2013-10-07 12:39:39 来源: 作者: 【 】 浏览:82
Tags:9.3.2 声明 保护 成员

9.3.2  声明类的保护成员

类成员除了有public和private访问说明符以外,我们还可以将类成员声明为protected。在类的内部,protected关键字与private关键字具有相同的效果。类的保护成员只能被类的成员函数和类的友元函数访问(还能被友元类的成员函数访问-- 本章稍后将讨论友元类)。使用protected关键字,我们可以将CBox类重新定义成如下形式:

  1. // Box.h in Ex9_04  
  2. #pragma once  
  3. #include <iostream> 
  4. using std::cout;  
  5. using std::endl;  
  6.  
  7. class CBox  
  8. {  
  9. public:  
  10. // Base class constructor  
  11. CBox(double lv = 1.0, double wv = 1.0, double hv = 1.0):  
  12. m_Length(lv), m_Width(wv), m_Height(hv)  
  13. { cout << endl << "CBox constructor called"; }  
  14.  
  15. // CBox destructor - just to track calls  
  16. ~CBox()  
  17. { cout << "CBox destructor called" << endl; }  
  18.  
  19. protected:  
  20. double m_Length;  
  21. double m_Width;  
  22. double m_Height;  
  23. }; 

现在,3个数据成员仍然不能被普通的全局函数访问,从这方面来讲,它们实际上还是私有成员,但可以被派生类的成员函数访问。

试一试:使用保护成员

通过使用该版本的CBox类来派生CCandyBox类的新版本,并让CCandyBox类利用自己的成员函数Volume()访问基类的成员,我们就可以证实protected数据成员的用途。

  1. // CandyBox.h in Ex9_04  
  2. #pragma once  
  3. #include "Box.h"  
  4. #include <iostream> 
  5. using std::cout;  
  6. using std::endl;  
  7.  
  8. class CCandyBox: public CBox  
  9. {  
  10. public:  
  11. char* m_Contents;  
  12.  
  13. // Derived class function to calculate volume  
  14. double Volume() const  
  15. { return m_Length*m_Width*m_Height; }  
  16.  
  17. // Constructor to set dimensions and contents  
  18. // with explicit call of CBox constructor  
  19. CCandyBox(double lv, double wv, double hv, char* str = "Candy")  
  20.            :CBox(lv, wv, hv) // Constructor  
  21. {  
  22. cout << endl <<"CCandyBox constructor2 called";  
  23. m_Contents = new char[ strlen(str) + 1 ];  
  24. strcpy_s(m_Contents, strlen(str) + 1, str);  
  25. }  
  26.  
  27. // Constructor to set contents  
  28. // calls default CBox constructor automatically  
  29. CCandyBox(char* str = "Candy")  // Constructor  
  30. {  
  31. cout << endl << "CCandyBox constructor1 called";  
  32. m_Contents = new char[ strlen(str) + 1 ];  
  33. strcpy_s(m_Contents, strlen(str) + 1, str);  
  34. }  
  35.  
  36. ~CCandyBox()    // Destructor  
  37. {  
  38. cout << "CCandyBox destructor called" << endl;  
  39. delete[] m_Contents;  
  40. }  
  41. }; 

Ex9_04.cpp文件中的main()代码如下:

  1. // Ex9_04.cpp  
  2. // Using the protected access specifier  
  3. #include <iostream>         // For stream I/O  
  4. #include <cstring>          // For strlen() and strcpy()  
  5. #include "CandyBox.h" // For CBox and CCandyBox  
  6. using std::cout;  
  7. using std::endl;  
  8.  
  9. int main()  
  10. {  
  11. CCandyBox myCandyBox;  
  12. CCandyBox myToffeeBox(2, 3, 4, "Stickjaw Toffee");  
  13.  
  14. cout << endl 
  15. << "myCandyBox volume is " << myCandyBox.Volume()  
  16. << endl 
  17. << "myToffeeBox volume is " << myToffeeBox.Volume();  
  18. // cout << endl << myToffeeBox.m_Length
    // Uncomment this for an error  
  19.  
  20. cout << endl;  
  21. return 0;  

示例说明

在该示例中,我们通过调用派生类的成员函数Volume(),来计算两个CCandyBox对象的体积,该函数通过访问继承的成员m_Length、m_Width和m_Height而获得结果。这些成员在基类中被声明为protected,在派生类中仍然是protected。该程序产生下面的输出:

  1. CBox constructor called  
  2. CCandyBox constructor1 called  
  3. CBox constructor called  
  4. CCandyBox constructor2 called  
  5. myCandyBox volume is 1  
  6. myToffeeBox volume is 24  
  7. CCandyBox destructor called  
  8. CBox destructor called  
  9. CCandyBox destructor called  
  10. CBox destructor called 

输出证实,两个CCandyBox对象的体积计算是正确的。第一个对象具有通过调用默认CBox构造函数获得的默认尺寸,因此其体积是1。第二个对象的尺寸是由声明中的初值确定的。

输出同时显示出构造函数和析构函数的调用次序,可以看出每个派生类对象都是分两步被销毁的。

注意:

派生类对象析构函数的调用顺序与构造函数相反。这是一条普遍适用的规则。创建对象时首先调用基类的构造函数,然后调用派生类的构造函数;而销毁对象时首先调用派生类的析构函数,然后才调用基类的析构函数。

通过解除main()函数中return语句前面那条语句的注释状态,我们可以证明基类的protected成员在派生类中仍然是protected。如果那样做,我们将得到下面这条来自编译器的出错消息:

  1. error C2248: 'm_Length': cannot access
    protected member declared in class 'CBox' 

该消息非常清楚地指出,m_Length成员是不可访问的。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇9.3.3 继承类成员的访问级别 下一篇9.2.2 基类的派生类

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: