c++/c学习笔记--补遗

本文介绍了C++11中的自定义字面量操作符,包括不同类型的字面量操作符的定义及用法。同时,探讨了强类型枚举的引入,强调其强作用域和转换限制特性。还讨论了C++11后联合体的变化,不再要求类型为POD,并展示了如何处理包含非POD类型的匿名联合体。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 用户自定义自面类型。第一次看到支持这个,很是吃惊!
    1. 如果字面量为整形数,那么字面量操作符只可接受unsigned long long。
    2. 如果字面为浮点数时,则字面可以接受的是long double;
    3. 如果字面量为字符串,则字面量操作符函数只可接受const char*,和size_t为参数,此size_t由编译器自动传入值。
    4. 如果字面量为字符,则字面量操作符函数只可一个char为参数。
      #include <iostream>
      #include <cctype>
      using namespace std;
      
      void operator "" _C(char t) {
          cout <<(char) toupper(t)<<endl;
      }
      void operator "" _S(const char* t,size_t n) { //此处n为隐式直接传入,不需要在显示指定,其根据传入字符串长度,由编译器传入
          int i =0;
          while(i < n) {
              cout << (char)toupper(*(t+i++));
          }
          cout << endl;
      }
      void operator "" _I(unsigned long long i) {
          cout << "this is a long long !"<<endl;
      }
      void operator "" _F(long double t) {
          cout << "in double long F"<<endl;
      }
      int main() {
          "ddd mfdfdafjda,fdfd"_S;//DDD MFDFDAFJDA,FDFD
          3456789876543_I;//this is a long long !
          'v'_C;//V
          3.44_F;//in double long F
      }
      
    5. 可以有返回值,所以,这个很是方便用于赋值。
    6. 尽量在后缀之前添加_,若不添加编译器会有警告。
    7. opeartor "" 和符后之后应有空格,且我们只能定义后缀,不能定义前缀。
  2. 原生态字符串的支持,类似于c#中@字符串
    1. #include <iostream>
      #include <cctype>
      using namespace std;
      
      int main() {
      	char* c = R"(hello \n
      zaijian)";
      	cout << c;
      
      
      }
      
    2. 这个当然也可结合字符串前缀来使用,如u8,U,u,其前缀分别是u8R,UR,uR
  3. 枚举类型
    1. 在c++中枚举类型是一个奇怪的问题,就是具名的enum类型的名字,以及enum的名字都是全局可见的。如
      enum type{a,b,};
      enum category{a,b};
      这二者在c++中会编译时报错 erro redeclareation.
    2. 当然,我们可以通过namespace来分割两个枚举类型的,但这个解决方案也容易出错,当然我们可以通过类的方式封装枚举,这样可能会较好的解决这个问题,但太麻烦了。
    3. 在c++11中提出了强类型枚举可以较好的解决这个问题,其声明在enum后添加class说明即可。其优点:
      1. 强作用域 ,即强类型枚举枚举成员的名称不会输出到其父类作用域空间
      2. 转换限制,强类型枚举成员的值不可以与整型隐式地相互转换。
      3. 可以指定底层类型。默认为int型实现,但也可以显示指定底导类型。
        #include <iostream>
        using namespace std;
        enum class type : char {a=1,b=127};
        enum class catagory{a,b};
        void func (type b){
        	cout <<sizeof(b);
        }
        
        int main() {
        	//func(a); 报错,必须显示传入
        	func(type::a);
        }
  4. 在c++11后,联合体对类型的限制取消。原要求其类型必须是pod,而现在无此要求。可以像一个类型一样来定义联合,但必须自定义其相关的类的构造。
    1. #include <iostream>
      #include <string>
      using namespace std;
      
      union r{
      	double x;
      	string t;
      public :
      	r(){
      		new (&t) string;
      	}
      	~r(){
      		t.~string();
      	}
      };
      int main() {
      r a;
      }
    2. 当然,我们可以给匿名union通过其他手段给予值,特别是当其内是完全类型时。此时这样的为可以称为 union like class
      #include <iostream>
      #include <string>
      using namespace std;
      struct student{
      	int age;
      	bool agenda;
      	student(bool g,int a):age(a),agenda(g){}
      };
      class qq{
      public:
      	enum class type {student,native,foreigner};
      	qq(bool g,int a):s(g,a){
      		t = type::student;
      	}
      	qq(int i):id(i){
      		t = type::native;
      	}
      	qq(string a):name(a){
      		t = type::foreigner;
      	}
      	~qq(){
      		if(t == type::foreigner){
      			name.~string();
      		}
      	}
      
      private:
      		type t;
      		union{
      			student s;
      			int id;
      			string name;
      		};
      
      };
      int main() {
      qq(true,4);
      qq("polly");
      }
      从这个例程可以看出的是如果我们不定义析构函数,则会报错,原因是由于其析构函数是被定义为删除的,具体分析,其主要原因是匿名联合体中采用了string这个非Pod类型,但由于我们采用了匿名的联合体,union难以显示定义其析构函数,故若在类中不定义析构函数,则将析构函数将定义为delete,而我们显示定义类的析构函数,需要针对匿名联合体中非pod的类型string作为定义析构。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值