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

#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类型
c++11union类型中允许出现自定义类型成员,标准库类型成员。

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


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

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

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

这里讲述其别名功能。

typedef std::vector<std::string> strvec;
using stdvec2 = std::vector<std::string>;

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

template<typename T>
using MapString = std::map<T, char*>;
MapString<int> 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(){
    f<Test>(10);
    f<int>(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 A<T*>
{
public:
    A(T* t)
    {
        printf("A2_addr_%x_value_%d\n", t, *t);
    }
};

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

在这里插入图片描述
类模板的特化与函数模板的重载还是不同的。
特化时,只能通过对通用版本的模板参数添加修饰符或用具体类型代替来达到特化效果。像函数重载中形如T::foo这样的操作是不允许的。

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

raindayinrain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值