学习继承和虚析构函数

练习代码,该说的都在代码和注释里:

  1 #include <string>
  2 
  3 class BaseClass 
  4 {
  5 private:
  6     int pri;
  7 protected:
  8     int pro;
  9 public:
 10     int pub;
 11 
 12     BaseClass()
 13     {
 14         printf("调用父类的构造函数!\n");
 15         to_string();
 16     }
 17 
 18     // 将析构函数设置为虚函数,以便在应用多态特征的时候,能够调用子类的析构函数释放子类动态申请的空间
 19     virtual ~BaseClass()    
 20     {
 21         printf("调用父类的析构函数!\n");
 22     }
 23     virtual void to_string()
 24     {
 25         printf("调用父类的to_string:我是父类!\n");
 26     }
 27     void do_something()
 28     {
 29         printf("我什么也没干!\n");
 30     }
 31 };
 32 
 33 class DerivedClassPub : public BaseClass
 34 {
 35 private:
 36     char* name;
 37 public:
 38     DerivedClassPub()
 39     {
 40         printf("调用子类的构造函数!\n");
 41         pub = 1;    // 还是public
 42         pro = 1;    // 还是protected
 43 //        pri = 1; 非法,不可访问
 44         const char* str = "小强";
 45         name = new char[strlen(str)+1];
 46         strcpy(name, str);
 47         to_string();
 48     }
 49     ~DerivedClassPub()
 50     {
 51         printf("调用子类的析构函数!\n");
 52 
 53         // 如果父类的析构函数不是虚函数,在应用多态特性时:如使用父类的指针或者引用指向子类时,子类的析构函数不会被调用,动态申请的空间无法被释放
 54         delete name;
 55         name = NULL;
 56     }
 57     void to_string()
 58     {
 59         printf("调用子类的to_string:我是子类!我的名字是:%s\n", name);
 60     }
 61     void do_something()
 62     {
 63         printf("我在跑步!\n");
 64     }
 65 };
 66 
 67 class DerivedClassPro : protected BaseClass
 68 {
 69 public:
 70     DerivedClassPro()
 71     {
 72         pub = 1;    // 变成protected
 73         pro = 1;    // 还是protected
 74 //        pri = 1; 非法,不可访问
 75     }
 76     ~DerivedClassPro(){}
 77 };
 78 
 79 class DerivedClassPri : private BaseClass
 80 {
 81 public:
 82     DerivedClassPri()
 83     {
 84         pub = 1;    // 变成private
 85         pro = 1;    // 变成private
 86 //        pri = 1; 非法,不可访问
 87     }
 88     ~DerivedClassPri(){}
 89 };
 90 
 91 class AnotherBaseClass
 92 {
 93 public:
 94     AnotherBaseClass()
 95     {
 96         printf("调用父类的构造函数!\n");
 97     }
 98     ~AnotherBaseClass()
 99     {
100         printf("调用父类的析构函数!\n");
101     }
102 };
103 class AnotherDerivedClass : public AnotherBaseClass
104 {
105 public:
106     AnotherDerivedClass()
107     {
108         printf("调用子类的构造函数!\n");
109     }
110     ~AnotherDerivedClass()
111     {
112         printf("调用子类的析构函数!\n");
113     }
114 };
115 
116 int main()
117 {
118     // 构造的时候,先调用父类的构造函数,若其中调用了任何虚函数和非虚函数,均是父类的函数,因为此时还没构造出子类的那部分,换句话说,现在才构造了一半
119     BaseClass* base = new DerivedClassPub();
120 
121     // 因为析构函数是虚函数,所以调用子类的析构函数,之后再调用父类的析构函数,为什么?
122     printf(">> 当析构函数是虚函数时:\n");
123     delete base;
124     printf("<< 结束!\n\n\n");
125     base = NULL;
126 
127     AnotherBaseClass* another_base = new AnotherDerivedClass();
128     printf(">> 当析构函数不是虚函数时:\n");
129     delete another_base;
130     printf("<< 结束!\n\n\n");
131     another_base = NULL;
132 
133     DerivedClassPub* d = new DerivedClassPub();
134     printf(">> 当析构函数是虚函数时:\n");
135     delete d;
136     printf("<< 结束!\n\n\n");
137     d = NULL;
138 
139     AnotherDerivedClass* ad = new AnotherDerivedClass();
140     printf(">> 当析构函数不是虚函数时:\n");
141     delete ad;
142     printf("<< 结束!\n\n\n");
143     ad = NULL;
144 
145     return 0;
146 }

输出结果:

调用父类的构造函数!
调用父类的to_string:我是父类!
调用子类的构造函数!
调用子类的to_string:我是子类!我的名字是:小强
>> 当析构函数是虚函数时:
调用子类的析构函数!
调用父类的析构函数!
<< 结束!


调用父类的构造函数!
调用子类的构造函数!
>> 当析构函数不是虚函数时:
调用父类的析构函数!
<< 结束!


调用父类的构造函数!
调用父类的to_string:我是父类!
调用子类的构造函数!
调用子类的to_string:我是子类!我的名字是:小强
>> 当析构函数是虚函数时:
调用子类的析构函数!
调用父类的析构函数!
<< 结束!


调用父类的构造函数!
调用子类的构造函数!
>> 当析构函数不是虚函数时:
调用子类的析构函数!
调用父类的析构函数!
<< 结束!


请按任意键继续. . .

 

 

 

 

posted @ 2013-09-28 00:24  铁甲小宝  阅读(305)  评论(0编辑  收藏  举报