c++11--变长参数宏,final与override,委托构造,union,using,模板重载和类型匹配

发布时间:2026/7/30 17:15:54

c++11--变长参数宏,final与override,委托构造,union,using,模板重载和类型匹配 1.变长参数宏定义及__VA_ARGS__C99中可使用变长参数空定义即在宏定义参数列表最后一个参数为省略号。预定义宏__VA_ARGS__可在宏定义实现部分替换省略号代表的内容。#include stdio.h #define LOG(...) {\ fprintf(stderr, %s:Line %d:\t, __FILE__, __LINE__);\ fprintf(stderr, __VA_ARGS__);\ fprintf(stderr, \n);\ } int main() { int x 3; LOG(x%d, x); return 0; }2.final与overridefinal可使得类型指定相应的虚函数对派生类来说不可被继续重载。#include iostream class B { public: virtual void fun() final { printf(Base_fun()\n); } }; class D1 : public B { public: void fun() // err { printf(D_fun()\n); } }; class D2 :public B { }; class DD : public D2 { public: void fun() // err { printf(DD_fun()\n); } }; int main() { }被final修饰的虚函数无法在直接派生类和间接派生类被重载。override可使得类型定义的函数必须是基类某个虚函数的重载时才可通过编译。#include iostream class B { public: virtual void fun() { } }; class D : public B { public: void fun() override { } void fun(int) override // err { } }; int main() { return 0; }类型中被override修饰的函数编译器将检查确保此函数重载了直接基类或间接基类的某个虚函数时方可编译通过。3.委托构造#include iostream using namespace std; class Base { public: Base(char c){ cout Base_ c endl; } }; class DCExcept{ public: DCExcept(double d) try:DCExcept(1, d){ cout Run the body. endl; } catch(...){ cout caught exception. endl; } private: DCExcept(int i, double d):b(b) { cout going to throw! endl; } int type; double data; Base b; }; int main() { DCExcept a(1.2); return 0; }新标志支持委托构造上述DCExcept(double d)是委托构造函数DCExcept(int i, double d)是委托构造的目标构造函数。关于委托构造注意点(1). 委托构造函数初始化列表除了指定目标构造函数的委托信息不可包含其他任何信息。这样保证类的初始化只通过目标构造函数执行一次。(2). 触发委托构造函数时的执行顺序为a.通过目标构造函数完成构造阶段执行目标构造的函数体。b.执行委托构造的函数体。c.采用委托构造时支持上述用try修饰目标构造函数。这样可像上述在委托构造中添加catch语句来捕获目标构造中可能抛出的异常。4.union类型c11中union类型中允许出现自定义类型成员标准库类型成员。#include iostream class B { public: B(){ printf(B()\n); } B(int i){ printf(B(int)\n); } B(const B){ printf(B(const)\n); } int i; }; class A { public: A(int i) { printf(A(int)\n); } ~A() { } // union类型特点在于只分配内存不执行构造过程。 // 其他c类型通过new动态得到对象时执行内存分配对象构造两个过程。 union { B n1; B b; }; }; int main() { A a(1); return 0; }值得注意的是union对象在动态构造阶段只是分配了内存不触发union对象的构造。5.usingusing在c中主要用于两种目的(1).提升命名空间可见性(2).别名功能这里讲述其别名功能。typedef std::vectorstd::string strvec; using stdvec2 std::vectorstd::string;上述利用typedef和using均可实现类型别名功能。但using还可用于模板编程时的别名typedef则无法达到此效果。templatetypename T using MapString std::mapT, char*; MapStringint numberedString;6.模板重载和类型匹配6.1.函数模板支持重载#include iostream struct Test{ typedef int foo; }; template typename T void f(typename T::foo){ printf(T::foo\n); } template typename T void f(T){ printf(T\n); } int main(){ // 1.推断模板参数隐式或显式这里是显式 // 2.结合模板定义得到实例定义非模板实现实例。不合法的定义不会生成实例。 // 3.接触实参进行函数匹配 fTest(10); fint(10); return 0; }c支持模板函数的重载。在存在多个模板重载版本时总是试图先用受限版本去匹配再用非受限版本去匹配。6.2.类模板支持特化#include iostream template typename T class A { public: A(T t) { printf(A1_value_%d\n, t); } }; template typename T class AT* { public: A(T* t) { printf(A2_addr_%x_value_%d\n, t, *t); } }; int main(){ int t 11; // 1.模板类型推断显式或隐式-这里是显式 // 2.基于模板定义结合模板类型推断得到实例定义。不合法的定义不会生成实例。 // AT*对于Aint来说是非法的因为int不是指针类型所以不会生成Aint实例。 // 3.结合实参进行函数匹配 Aint a(10); // 1.模板类型推断显式或隐式-这里是显式 // 2.基于模板定义结合模板类型推断得到实例定义。不合法的定义不会生成实例。 // 这里有两个合法的实例定义 // 3.结合实参进行函数匹配 // 实际匹配到T*版本的实例定义 // 4.针对匹配版本进行使用 Aint* aa(t); return 0; }类模板的特化与函数模板的重载还是不同的。特化时只能通过对通用版本的模板参数添加修饰符或用具体类型代替来达到特化效果。像函数重载中形如T::foo这样的操作是不允许的。

相关新闻