zoukankan      html  css  js  c++  java
  • 学习类中的const和static类型

    上代码,该说的都在代码及注释里:

      1 #include <stdlib.h>
      2 #include <stdio.h>
      3 #include <string>
      4 
      5 using namespace std;
      6 
      7 class BaseClass
      8 {
      9 protected:
     10     // 普通变量
     11     int data;
     12 
     13     // 地址不可变,但内容可变的常量
     14     // 必须在初始值设定项列表中初始化
     15     char* const name;
     16 private:
     17 
     18     // 内容不可变常量
     19     // 必须初始值设定项列表中初始化
     20     const int id;
     21 
     22     // 类的全部实例共享的变量
     23     // 在任意函数中都可以赋值,但是,这样做不符合其static的意义
     24     // 合理的使用方式是在类外初始化,否则没有合适的赋初值的方式
     25     static int count;
     26 
     27     // 类的全部实例共享的常量
     28     // 不能在初始值设定项列表中初始化,初始值设定项列表只能处理非static类型的成员
     29     // 不能在任何函数中赋值
     30     // 所以只能类外初始化
     31     static const int max;
     32 public:
     33     // 关于“是不是所有成员函数都可以声明称虚函数的问题”
     34     // 下面的语句不合法!
     35     // error C2633: “BaseClass”:“inline”是构造函数的唯一合法存储类
     36     // virtual BaseClass(){}
     37     
     38     // 关于“const类型的成员变量初始化的问题”
     39     // 下面的语句不合法!
     40     // error C2758: “BaseClass::idx和BaseClass::name””: 必须在构造函数基/成员初始值设定项列表中初始化
     41     // BaseClass(){}
     42 
     43     // 合法定义
     44     inline BaseClass(const char* str): id(count++), name((char*)malloc(strlen(str)))
     45     {
     46         printf("基类构造函数!
    ");
     47         strcpy(name, str);
     48         data = 0;
     49     }
     50     inline ~BaseClass()
     51     {
     52         printf("基类析构函数!
    ");
     53 
     54         // 以下语句导致基类析构函数卡住,不知道什么原因,这句话即使放到派生类中,也会导致派生类析构卡住,停止却不报错,很奇怪的现象~
     55         // 无论是new还是malloc的空间,都会卡住
     56         // if (name)
     57         //        free(name);
     58 
     59         // 即使用delete也会卡住
     60         // delete name;
     61     }
     62     
     63     // 关于“虚函数是否能是static类型的问题”
     64     // 下面的语句不合法!
     65     // error C2216: “virtual”不能和“static”一起使用
     66     // virtual static int doSomething() = 0;
     67     
     68     // 合法定义,函数体为const类型
     69     virtual int get_id() const {return id;}
     70     virtual int get_max() const {return max;}
     71 
     72     // 合法定义,传入的参数为const类型
     73     virtual void set_data(const int& d){data = d;}
     74 
     75     // 关于“const修饰的成员函数的问题”
     76     // 下面的语句不合法!
     77     // error C3490: 由于正在通过常量对象访问“data”,因此无法对其进行修改
     78     // 有const修饰时,类的全部成员变量变成了const类型
     79     // 例如:const char* name 会变成 const char* const name; int data 变成了 const int data;
     80     // virtual void set_data(const int& d) const {data = d;}
     81 
     82     // 合法定义
     83     virtual void print_string() const {
     84         printf("My id is %d , my name is %s and my data is %d.
    ", id, name, data);
     85     }
     86     
     87 };
     88 
     89 // 下面的语句不合法!
     90 // error C2720: “BaseClass::cnt”: 成员上的“static ”存储类说明符非法
     91 // static int BaseClass::cnt = 0;
     92 
     93 // 合法赋值表达式,必须有类型说明:int,否则不合法
     94 int BaseClass::count = 1;
     95 
     96 // 下面的语句不合法!
     97 // error C2373: “max”: 重定义;不同的类型修饰符
     98 // int BaseClass::max = 1024;
     99 
    100 // 合法赋值表达式,必须同时有const和int
    101 const int BaseClass::max = 1024;
    102 
    103 class DerivedClass : public BaseClass
    104 {
    105 private:
    106     char* subname;
    107 public:
    108     // 由于基类没有默认构造函数,子类必须定义构造函数,而且必须是对应参数及类型的构造函数,否则出现错误:
    109     // error C2512: “DerivedClass”: 没有合适的默认构造函数可用
    110     // error C2512: “BaseClass”: 没有合适的默认构造函数可用
    111     // DerivedClass(){};
    112     
    113     // 下面的语句没有意义,相当于创建的一个临时变量,语句结束即销毁
    114     // DerivedClass(const char* str){BaseClass(str);};
    115 
    116     // 合法定义
    117     DerivedClass(const char* str):BaseClass(str)
    118     {
    119         printf("派生类构造函数!
    ");
    120         subname = NULL;
    121     };
    122 
    123     ~DerivedClass()
    124     {
    125         printf("派生类析构函数!
    ");
    126 
    127         // 以下语句会导致delete操作时卡住,不知道为什么,很奇怪~
    128         // if (subname)
    129         //     free(subname);
    130         // subname = NULL;
    131 
    132         // 下面的语句同上,莫名其妙的卡住
    133         // delete subname;
    134 
    135     }
    136 
    137     void set_sub_name(const char* str)
    138     {
    139         if(subname)
    140             free(subname);
    141         subname = new char[strlen(str)];
    142         strcpy(subname, str);
    143     }
    144 
    145     void print_string() const 
    146     {
    147         // 下面的语句不合法!
    148         // 因为id是private类型,不能被子类访问
    149         // 而protected类型可以,例如name和data
    150         // error C2248: “BaseClass::id”: 无法访问 private 成员(在“BaseClass”类中声明)
    151         // printf("My id is %d , my name is %s and my data is %d.
    ", id, name, data);
    152 
    153         // 下面的语句不合法
    154         // 因为有const修饰的函数无法调用派生类和基类的非const类型的函数
    155         // error C2662: “BaseClass::set_data”: 不能将“this”指针从“const DerivedClass”转换为“BaseClass &”
    156         // set_data(1);
    157 
    158         // 合法调用
    159         BaseClass::print_string();
    160         
    161         // 合法调用
    162         // const修饰的函数只能调用派生类和基类的const函数,下面的Base::get_id()便是一个有const修饰的函数
    163         // 这是派生类的const函数访问基类的private函数的唯一方法,访问他们的const类型的get函数,但是显然const类型的函数无法修改private类型的变量,也无法修改其他类型的变量
    164         printf("I'm a DerivedClass, my subname is %s and I can see max = %d.
    ", subname, BaseClass::get_max());
    165 
    166     };
    167 };
    168 
    169 int main()
    170 {
    171 
    172     {
    173         // 测试构造函数的顺序
    174         printf(">> 构造函数顺序依次是:
    ");
    175         DerivedClass a("Liu");
    176         printf("<< 测试结束!
    
    ");
    177         a.print_string();
    178         printf(">> 析构函数顺序依次是:
    ");
    179         // 测试析构函数的顺序
    180     }
    181     printf("<< 测试结束!
    
    ");
    182     DerivedClass* b = new DerivedClass("Wang");
    183     b->set_sub_name("Jone");
    184     b->print_string();
    185     // 测试free能否出发析构函数
    186     printf(">> 测试free能否触发析构函数:
    ");
    187     free(b);
    188     printf("<< 测试结束!
    
    ");
    189     b = NULL;
    190 
    191     // 测试delete能否触发析构函数
    192     DerivedClass* c = new DerivedClass("Zhao");
    193     c->set_sub_name("Mike");
    194     c->print_string();
    195     printf(">> 测试delete能否触发析构函数:
    ");
    196     delete c;
    197     printf("<< 测试结束!
    
    ");
    198     c = NULL;
    199 
    200     // 合法,释放堆中的空间
    201     int* arr1 = new int[10];
    202     free(arr1);
    203 
    204     // 语法合法,但执行非法,通过free释放栈中的空间
    205     // int arr2[10] = {0};
    206     // free(arr2);
    207 
    208     // 语法合法,但执行非法,通过free释放常量区的空间
    209     // char* arr3 = "Hello !";
    210     // free(arr3);
    211 
    212     getchar();
    213     return 0;
    214 }

    输出结果是:

    >> 构造函数顺序依次是:
    基类构造函数!
    派生类构造函数!
    << 测试结束!
    
    My id is 1 , my name is Liu and my data is 0.
    I'm a DerivedClass, my subname is (null) and I can see max = 1024.
    >> 析构函数顺序依次是:
    派生类析构函数!
    基类析构函数!
    << 测试结束!
    
    基类构造函数!
    派生类构造函数!
    My id is 2 , my name is Wang and my data is 0.
    I'm a DerivedClass, my subname is Jone and I can see max = 1024.
    >> 测试free能否触发析构函数:
    << 测试结束!
    
    基类构造函数!
    派生类构造函数!
    My id is 3 , my name is Zhao and my data is 0.
    I'm a DerivedClass, my subname is Mike and I can see max = 1024.
    >> 测试delete能否触发析构函数:
    派生类析构函数!
    基类析构函数!
    << 测试结束!
  • 相关阅读:
    杨辉三角1
    岛屿与周长
    什么是计算机语言
    爬虫爬取视图片
    爬虫爬取文字生成词云
    英文词频统计
    回溯法~0-1背包的实现
    java Swing图形化界面
    棋盘覆盖
    敏捷软件开发 10~12章
  • 原文地址:https://www.cnblogs.com/zanzan101/p/3342023.html
Copyright © 2011-2022 走看看