【学习日志】2022.11.11 合同矩阵、惯性指数、委托构造、继承控制、=delete、可变参数模板类

news2025/7/23 5:59:16

 

class Info
{
public:
    Info() : Info(1) { }    // 委托构造函数
    Info(int i) : Info(i, 'a') { } // 既是目标构造函数,也是委托构造函数
    Info(char e): Info(1, e) { }

private:
    Info(int i, char e): type(i), name(e) { /* 其它初始化 */ } // 目标构造函数
    int  type;
    char name;
    // ...
};

class B1 final {}; // 此类不能被继承
//class D1: public B1 {}; // error!

class B
{
public:
//  virtual void func() override // error! 指定了重写但实际并没重写,没有基类
//  {
//      cout << __func__ << std::endl;
//  }
    virtual void f() const
    {
        cout << __func__ << std::endl;
    }
    virtual void fun()
    {
        cout << __func__ << std::endl;
    }
};

class D : public B
{
public:
    virtual void f(int)      // ok! 隐藏,由于没有重写同名函数B::f,在D中变为不可见
    {
        cout << "hiding: " <<__func__ << std::endl;
    }
//  virtual void f() override   // error! 指定了重写但实际并没重写,类型声明不完全相同
//  {
//      cout << __func__ << std::endl;
//  }
    virtual void fun() override final // ok! 指定了重写实际上也重写了,同时,指定为最终,后代类中不能再重写此虚函数
    {
        cout << __func__ << std::endl;
    }
};

class D2 : public D
{
public:
    virtual void f() const      // ok! 重写B::f(),同时,由于没有重写D::f(int),在D2中变不可见
    {
        cout << __func__ << std::endl;
    }
//  virtual void fun() // error! 基类的此虚函数被指定为最终,不能被重写,虽然没有显示指定"override"
//  {
//      cout << __func__ << std::endl;
//  }
//  virtual void fun() override // error! 基类的此虚函数被指定为最终,不能被重写
//  {
//      cout << __func__ << std::endl;
//  }
};

class X
{ 
public: 
    X(){}  // 手动定义默认构造函数

    X(int i)
    { 
        a = i; 
    }
        
private: 
    int a; 
}; 

X obj; //必须手动定义默认构造函数X(){} 才能编译通过

原本期望编译器自动生成的默认构造函数却需要程序员手动编写,即程序员的工作量加大了。此外,手动编写的默认构造函数的代码执行效率比编译器自动生成的默认构造函数低。

类的其它几类特殊成员函数也和默认构造函数一样,当存在用户自定义的特殊成员函数时,编译器将不会隐式的自动生成默认特殊成员函数,而需要程序员手动编写,加大了程序员的工作量。类似的,手动编写的特殊成员函数的代码执行效率比编译器自动生成的特殊成员函数低。

C++11 标准引入了一个新特性:"=default"函数。程序员只需在函数声明后加上“=default;”,就可将该函数声明为 "=default"函数,编译器将为显式声明的 "=default"函数自动生成函数体。

class X
{ 
public: 
    X()= default; //该函数比用户自己定义的默认构造函数获得更高的代码效率
    X(int i)
    { 
        a = i; 
    }
        
private: 
    int a; 
}; 

X obj;

"=default"函数特性仅适用于类的特殊成员函数,且该特殊成员函数没有默认参数。例如:

class X
{
public:
    int f() = default;      // err , 函数 f() 非类 X 的特殊成员函数
    X(int, int) = default;  // err , 构造函数 X(int, int) 非 X 的特殊成员函数
    X(int = 1) = default;   // err , 默认构造函数 X(int=1) 含有默认参数
};

"=default"函数既可以在类体里(inline)定义,也可以在类体外(out-of-line)定义。例如:

class X
{
public:
    X() = default; //Inline defaulted 默认构造函数
    X(const X&);
    X& operator = (const X&);
    ~X() = default;  //Inline defaulted 析构函数
};

X::X(const X&) = default;  //Out-of-line defaulted 拷贝构造函数
X& X::operator= (const X&) = default;   //Out-of-line defaulted  拷贝赋值操作符

"=delete"函数

为了能够让程序员显式的禁用某个函数,C++11 标准引入了一个新特性:"=delete"函数。程序员只需在函数声明后上“=delete;”,就可将该函数禁用。

class X
{
public:
    X();
    X(const X&) = delete;  // 声明拷贝构造函数为 deleted 函数
    X& operator = (const X &) = delete; // 声明拷贝赋值操作符为 deleted 函数
};

int main()
{
    X obj1;
    X obj2=obj1;   // 错误,拷贝构造函数被禁用

    X obj3;
    obj3=obj1;     // 错误,拷贝赋值操作符被禁用

    return 0;
}

"=delete"函数特性还可用于禁用类的某些转换构造函数,从而避免不期望的类型转换:

class X
{
public:
    X(double)
    {

    }

    X(int) = delete;
};

int main()
{
    X obj1(1.2);
    X obj2(2); // 错误,参数为整数 int 类型的转换构造函数被禁用

    return 0;
}

模板的改进

右尖括号>改进

在C++98/03的泛型编程中,模板实例化有一个很繁琐的地方,就是连续两个右尖括号(>>)会被编译解释成右移操作符,而不是模板参数表的形式,需要一个空格进行分割,以避免发生编译时的错误。

template <int i> class X{};
template <class T> class Y{};

int main()
{
    Y<X<1> > x1;    // ok, 编译成功
    Y<X<2>> x2;     // err, 编译失败

    return 0;
};

在实例化模板时会出现连续两个右尖括号,同样static_cast、dynamic_cast、reinterpret_cast、const_cast表达式转换时也会遇到相同的情况。C++98标准是让程序员在>>之间填上一个空格,在C++11中,这种限制被取消了。在C++11标准中,要求编译器对模板的右尖括号做单独处理,使编译器能够正确判断出">>"是一个右移操作符还是模板参数表的结束标记。

模板的别名

#include <iostream>
#include <type_traits> //std::is_same
using namespace std;

using uint = unsigned int;
typedef unsigned int UINT;
using sint = int;

int main()
{
    //std::is_same 判断类型是否一致
    //这个结构体作用很简单,就是两个一样的类型会返回true
    cout << is_same<uint, UINT>::value << endl; // 1

    return 0;
}

函数模板的默认模板参数

C++11之前,类模板是支持默认的模板参数,却不支持函数模板的默认模板参数:

//1、普通函数带默认参数,c++98 编译通过,c++11 编译通过
void DefParm(int m = 3) {}

//2、类模板是支持默认的模板参数,c++98 编译通过,c++11 编译通过
template <typename T = int>
class DefClass {};

//3、函数模板的默认模板参数, c++98 - 编译失败,c++11 - 编译通过
template <typename T = int> void DefTempParm() {}

类模板的默认模板参数必须从右往左定义,数模板的默认模板参数则没这个限定:

template<class T1, class T2 = int> class DefClass1;
template<class T1 = int, class T2> class DefClass2;   // 无法通过编译

template<class T, int i = 0> class DefClass3;
template<int i = 0, class T> class DefClass4;         // 无法通过编译

template<class T1 = int, class T2> void DefFunc1(T1 a, T2 b);
template<int i = 0, class T> void DefFunc2(T a);

template<class ... T> void func(T ... args)//T叫模板参数包,args叫函数参数包
{//可变参数模板函数

}

func();    // OK:args不含有任何实参
func(1);    // OK:args含有一个实参:int
func(2, 1.0);   // OK:args含有两个实参int和double

 

template<class ... T> void func(T ... args)
{//可变参数模板函数
    //sizeof...(sizeof后面有3个小点)计算变参个数
    cout << "num = " << sizeof...(args) << endl;
}

int main()
{
    func();     // num = 0
    func(1);    // num = 1
    func(2, 1.0);   // num = 2

    return 0;
}

  

//递归终止函数
void debug()
{
    cout << "empty\n";
}

//展开函数
template <class T, class ... Args>
void debug(T first, Args ... last)
{
    cout << "parameter " << first << endl;
    debug(last...);
}

int main()
{
    debug(1, 2, 3, 4);
    /*
    运行结果:
        parameter 1
        parameter 2
        parameter 3
        parameter 4
        empty
    */

    return 0;
}

非递归方式展开

template <class T>
void print(T arg)
{
    cout << arg << endl;
}

template <class ... Args>
void expand(Args ... args)
{
    int a[] = { (print(args), 0)... };
}

int main()
{
    expand(1, 2, 3, 4);

    return 0;
}

expand函数的逗号表达式:(print(args), 0), 也是按照这个执行顺序,先执行print(args),再得到逗号表达式的结果0。

同时,通过初始化列表来初始化一个变长数组,{ (print(args), 0)... }将会展开成( (print(args1), 0), (print(args2), 0), (print(args3), 0), etc...), 最终会创建一个元素只都为0的数组int a[sizeof...(args)]。

6.2 可变参数模板类

6.2.1 继承方式展开参数包

可变参数模板类的展开一般需要定义2 ~ 3个类,包含类声明和特化的模板类:

template<typename... A> class BMW{};  // 变长模板的声明

template<typename Head, typename... Tail>  // 递归的偏特化定义
class BMW<Head, Tail...> : public BMW<Tail...>
{//当实例化对象时,则会引起基类的递归构造
public:
    BMW()
    {
        printf("type: %s\n", typeid(Head).name());
    }

    Head head;
};

template<> class BMW<>{};  // 边界条件

int main()
{
    BMW<int, char, float> car;
    /*
    运行结果:
        type: f
        type: c
        type: i
    */

    return 0;
}

6.2.2 模板递归和特化方式展开参数包

template <long... nums> struct Multiply;// 变长模板的声明

template <long first, long... last>
struct Multiply<first, last...> // 变长模板类
{
    static const long val = first * Multiply<last...>::val;
};

template<>
struct Multiply<> // 边界条件
{
    static const long val = 1;
};

int main()
{
    cout << Multiply<2, 3, 4, 5>::val << endl; // 120

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/7624.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

UD4KB100-ASEMI智能家居专用整流桥UD4KB100

编辑-Z UD4KB100在D3K封装里采用的4个芯片&#xff0c;其尺寸都是72MIL&#xff0c;是一款智能家居专用整流桥。UD4KB100的浪涌电流Ifsm为125A&#xff0c;漏电流(Ir)为10uA&#xff0c;其工作时耐温度范围为-55~150摄氏度。UD4KB100采用光阻GPP芯片材质&#xff0c;里面有4颗…

【POJ No. 3134】幂运算 Power Calculus

【POJ No. 3134】幂运算 Power Calculus POJ 题目地址 【题意】 从x 开始&#xff0c;反复乘以x &#xff0c;可以用30次乘法计算x^31 平方运算可以明显地缩短乘法序列&#xff0c;以下是用8次乘法计算x^31 的方 法&#xff1a; 这不是计算x^31 的最短乘法序列。有很多方法只…

20221115使用google文档翻译SRT格式的字幕

20221115使用google文档翻译SRT格式的字幕 2022/11/15 18:52 &#xff08;一&#xff09;将SRT格式的字幕用WPS转换为DOCX的文档。 &#xff08;请上传 .docx、.pdf、.pptx 或 .xlsx 文件&#xff09; https://www.google.com.hk/?gws_rdssl Google 拍照搜索 Google 提供&a…

F - Double Chance(期望,数学,树状数组优化)[AtCoder Beginner Contest 276]

题目如下&#xff1a; F - Double Chance 题目链接 思路 or 题解&#xff1a; 期望公式&#xff1a;∑valp\sum val \times p∑valp 还可以细分&#xff1a; 如果两次抽出的值是相同的&#xff0c;都是 xxx&#xff0c;那么抽出的方案数为 cntxcntxcnt_x \times cnt_xcntx​c…

Allegro 274X格式gerber输出全流程详细介绍

Allegro 274X格式gerber输出全流程详细介绍 下面介绍Allegro gerber输出的全流程介绍 首先把光绘设置好 设置光钻孔精度 会出现对话框,勾选Enhanced Excellon format,点击close 输出钻孔文件,选择Auto Tool select,点击Drill 输出椭圆孔文件,默认设置,然后点击rout…

一套SCDM脚本建模与二次开发攻略

导读&#xff1a;ANSYS SpaceClaim Direct Modeler&#xff08;简称 SCDM&#xff09;&#xff0c;是基于直接建模思想的新一代3D建模和几何处理软件&#xff0c;摒弃了基于历史的概念建模的约束的概念&#xff0c;让我们轻松完成几何的创建与修改&#xff0c;不会带来传统CAD系…

【附源码】计算机毕业设计JAVA晨光文具店进销存系统设计与开发

【附源码】计算机毕业设计JAVA晨光文具店进销存系统设计与开发 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xf…

m基于STBC的MIMO通信系统性能仿真和信道容量仿真

目录 1.算法概述 2.仿真效果预览 3.核心MATLAB预览 4.完整MATLAB程序 1.算法概述 空时分组编码STBC&#xff08;Space Time Block Coding&#xff09;用在无线通信中传输一个数据流的多个拷贝。通过许多天线来产生数据的多种接收版本&#xff0c;提高数据传输的可靠性。接收…

4、Redis配置文件介绍

文章目录4、Redis配置文件介绍4.1、###Units单位###4.2、###INCLUDES包含###4.3、###网络相关配置4.3.1、bind4.3.2、protected-mode4.3.3、Port4.3.4、tcp-backlog4.3.5、timeout4.3.6、tcp-keepalive4.4、###GENERAL通用###4.4.1、daemonize4.4.2、pidfile4.4.3、loglevel4.4…

一次SpringBoot版本升级,引发的血案

前言 最近项目组升级了SpringBoot版本&#xff0c;由之前的2.0.4升级到最新版本2.7.5&#xff0c;却引出了一个大Bug。 到底是怎么回事呢&#xff1f; 1.案发现场 有一天&#xff0c;项目组的同事反馈给我说&#xff0c;我之前有个接口在新的测试环境报错了&#xff0c;具体…

从应用层深入Framework层,Android Framework 该如何学习?

对于咱们Android开发来说&#xff0c;一般来说都是干上个几年之后&#xff0c;都得要考虑进阶或者是转行的问题。但老话说转行穷三年&#xff0c;不到万不得已我想大多数人都 不会去放弃现在的岗位与薪资。 如果你还在干Android并且想要进阶&#xff0c;那么对Framework的了解…

ava面试八股文-基础概念二

Java面试八股文-基础概念二1.重载与重写的区别2.接口与抽象类区别3.Java集合类-Collection6.lambda表达式与匿名内部类的区别1.重载与重写的区别 重载是编译时多态&#xff0c;重写是运⾏时多态。 方法重写&#xff1a; &#xff08;1&#xff09;参数列表与被重写方法的参数列…

低代码维格云明细视图入门教程

功能简介 低代码维格云可以将基础的数据通过设置操作权限、查询条件、限制数据范围、设置字段显示来创建数据表的明细视图。 设置步骤 功能入口 具体见报表简介 操作权限 数据表是拥有操作权限类别最多的自定义图表,操作权限包括: 可导出可见流程日志可留言可打印可添加数…

C. Balanced Bitstring(思维+子字符串规律)

Problem - 1405C - Codeforces 一个比特串是一个只由0和1字符组成的字符串&#xff0c;如果这个比特串的每个大小为k的子串都有相同数量的0和1字符&#xff08;各为k2&#xff09;&#xff0c;那么这个比特串就被称为k平衡的。 给你一个整数k和一个只由0&#xff0c;1&#xf…

来自BAT的一份Java高级开发岗面试指南:金三银四必定面试无忧

作为一名即将求职的程序员&#xff0c;你的就业机会和风口会出现在哪里&#xff1f;在这种新环境下&#xff0c;工作应该选择大厂还是小公司&#xff1f;已有几年工作经验的老兵&#xff0c;又应该如何保持和提升自身竞争力&#xff0c;转被动为主动&#xff1f; 就目前大环境…

VMware16虚拟机添加硬盘(磁盘)和挂载硬盘(磁盘)

记录&#xff1a;317 场景&#xff1a;在VMware16虚拟机&#xff0c;安装了CentOS 7.9操作系统场景下&#xff0c;添加硬盘(磁盘)和挂载硬盘(磁盘)。 版本&#xff1a; 操作系统&#xff1a;CentOS 7.9 1.机器配置 机器名称&#xff1a;B200&#xff1b;主机名称&#xff…

企业级数据中台应用架构和技术架构

一、什么是数据中台 数据中台是一种将企业沉睡的数据变成数据资产&#xff0c;持续使用数据、产生智能、为业务服务&#xff0c;从而实现数据价值变现的系统和机制。通过数据中台提供的方法和运行机制&#xff0c;形成汇聚整合、提纯加工、建模处理、算法学习&#xff0c;并以…

【路径规划-VRP问题】基于遗传算法求解出租车网约车接送客车辆路径规划问题附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

好未来(TAL)喜忧参半的前景

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经认为好未来&#xff08;TAL&#xff09;的前景喜忧参半。一方面&#xff0c;好未来已成功转向了新业务领域&#xff0c;如内容解决方案和学习技术解决方案&#xff0c;其新的直播电商业务也有巨大的增长潜力。另一…

npm nvm cnpm常见指令

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、nvm开头操作1.安装nodejs2.查看当前正在使用的版本3.切换使用的nodejs版本二、npm开头的操作1.全局安装cnpm2.查看npm的版本4.运行项目5.安装路由5.1 vue3 的…