c++11--保证稳定性和兼容性

保证稳定性和兼容性

1.变长参数宏定义及__VA_ARGS__
C99中,可使用变长参数空定义,即在宏定义参数列表最后一个参数为省略号。
预定义宏__VA_ARGS__可在宏定义实现部分替换省略号代表的内容。

#include 
#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与override
final可使得类型指定相应的虚函数对派生类来说不可被继续重载。

#include 

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 

class B
{
public:
    virtual void fun()
    {

    }
};

class D : public B
{
public:
    void fun() override
    {

    }

    void fun(int) override // err
    {

    }
};

int main()
{
    return 0;
}

类型中被override修饰的函数,编译器将检查,确保此函数重载了直接基类或间接基类的某个虚函数时,方可编译通过。

通用为本,专用为末

1.委托构造

#include 
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;
}

c++11--保证稳定性和兼容性_第1张图片

新标志支持委托构造上述DCExcept(double d)是委托构造函数, DCExcept(int i, double d)是委托构造的目标构造函数。
关于委托构造注意点:
(1). 委托构造函数初始化列表除了指定目标构造函数的委托信息,不可包含其他任何信息。这样保证类的初始化只通过目标构造函数执行一次。
(2). 触发委托构造函数时的执行顺序为:
a.通过目标构造函数完成构造阶段,执行目标构造的函数体。
b.执行委托构造的函数体。
c.采用委托构造时,支持上述用try修饰目标构造函数。这样可像上述在委托构造中添加catch语句来捕获目标构造中可能抛出的异常。

2.union类型
c++11中union类型中允许出现自定义类型成员,标准库类型成员。

#include 

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 
    {
        int n;
        B b;
    };
};


int main()
{
    A a(1);
    return 0;
}

在这里插入图片描述
值得注意的是union对象在动态构造阶段,只是分配了内存,不触发union对象的构造。

3.using
using在c++中主要用于两种目的:
(1).提升命名空间可见性
(2).别名功能

这里讲述其别名功能。

typedef std::vector strvec;
using stdvec2 = std::vector;

上述利用typedef和using均可实现类型别名功能。
但using还可用于模板编程时的别名,typedef则无法达到此效果。

template
using MapString = std::map;
MapString numberedString;

4.模板重载和类型匹配
4.1.函数模板支持重载

#include 

struct Test{
    typedef int foo;
};

template 
void f(typename T::foo){
    printf("T::foo\n");
}

template 
void f(T){
    printf("T\n");
}

int main(){
    f(10);
    f(10);
    return 0;
}

在这里插入图片描述
c++支持模板函数的重载。在存在多个模板重载版本时,总是试图先用受限版本去匹配,再用非受限版本去匹配。

4.2.类模板支持特化

#include 

template 
class A
{
public:
    A(T t)
    {
        printf("A1_value_%d\n", t);
    }
};

template 
class A
{
public:
    A(T* t)
    {
        printf("A2_addr_%x_value_%d\n", t, *t);
    }
};

int main(){
    int t = 11;
    A a(10);
    A aa(&t);
    return 0;
}

c++11--保证稳定性和兼容性_第2张图片
类模板的特化与函数模板的重载还是不同的。
特化时,只能通过对通用版本的模板参数添加修饰符或用具体类型代替来达到特化效果。像函数重载中形如T::foo这样的操作是不允许的。

你可能感兴趣的:(1.3.语言-C++11,c++,开发语言)