令人迷惑的写法(五十六)

今天我们来看看一些在程序中迷惑的写法,下面的程序想要表达什么意思呢?

#include <iostream>
#include <string>

using namespace std;

template < class T >
class Test
{
public:
    Test(T t)
    {
        cout << "t = " << t << endl;
    }
};

template < class T >
void func(T a[], int len)
{
    for(int i=0; i<len; i++)
    {
        cout << a[i] << endl;
    }
}

int main()
{
    int a[5] = {1, 2, 3, 4, 5};
    
    Test<int> t(5);
    
    cout << endl;
    
    func(a, 5);

    return 0;
}

我们在类模板中用 class 来声明,但是我们在 main 函数中是用 int 类型来使用的,下来我们看看这样的写法在 C++ 编译器中支持吗?

我们看到编译器编译通过并且运行成功。那么我们不是用的 typename 来声明的泛指类型的嘛,这怎么用 class 了呢。这是因为历史上的一些原因,早期的 C++ 直接复用 class 关键字来定义模板,但是泛型编程针对的不只是类类型,class 关键字的复用使得代码出现二义性。下来我们来看看具有二义性的代码

#include <iostream>
#include <string>

using namespace std;

int a = 0;

class Test_1
{
public:
    static const int TS = 1;
};

class Test_2
{
public:
    struct TS
    {
        int value;
    };
};

template
< class T >
void test_class()
{
    T::TS * a;  // 这便出现了二义性
                // 1. 通过泛指类型 T 内部的数据类型 TS 定义指针变量 a (推荐的解读方式)
                // 2. 使用泛指类型 T 内部的静态成员变量 TS 与全局变量 a 进行乘法操作
}

int main()
{
    test_class<Test_1>();
    test_class<Test_2>();

    return 0;
}

我们通过在函数模板指定泛指类型为 Test_1,便是第 2 种解读方式,泛指类型为 Test_2 时,便是第 1 种解读方式。那么在这块是不是就出现了二义性呢?我们看看编译结果

我们看到编译器直接报错了,如果是一种类型的话,便让我们在前前面加上 typename,那么我们在模板中加上 typename,看看

编译器又报错了,它说 Test_1 中没有这种类型,肯定没有啊,只有一个成员变量而已。我们注释掉 Test_1 看看

编译通过了。那么 typename 诞生的原因是什么呢?用来自定义类类型内部的嵌套类型,不同类中的同一个标识符可能导致二义性,编译器无法直接辨识标识符究竟是什么。typename 的作用有两个:1、在模板定义中声明泛指类型;2、明确告诉编译器其后的标识符为类型。

那么下面的程序想要表达什么意思呢?

try...catch 用于分隔正常功能代码与异常处理代码,try...catch 可以直接将函数实分隔为两部分。函数声明和定义时可以直接指定可能抛出的异常类型,异常声明成为函数的一部分可以提高代码可读性。那么函数异常声明时有几个注意事项:1、函数异常声明是一种与编译器之间的契约;2、函数声明异常后就只能抛出声明的异常,抛出其他异常将导致程序运行终止,可以直接通过异常声明定义无异常函数。

下来我们还是以代码为例来进行说明

#include <iostream>
#include <string>

using namespace std;

int func(int i, int j) throw(int)
{
    if( (0 < j) && (j < 10) )
    {
        return (i + j);
    }
    else
    {
        throw '0';
    }
}

void test(int i) try
{
    cout << "func(i, i) = " << func(i, i) << endl;
}
catch(int i)
{
    cout << "Exception: " << i << endl;
}
catch(...)
{
    cout << "Exception..." << endl;
}

int main()
{
    test(5);
    
    test(10);
    
    return 0;
}

我们在 func 函数中异常只声明了 int,而抛出了字符型异常。我们来看看会导致程序运行终止嘛?

确实导致了程序的运行终止了,注意我们的程序中还有 catch(...) 都没能捕捉到 char  类型的异常。那么我们在声明的异常中加上 char 再来看看

程序正常的运行结束了。通过今天对一些迷惑写法的学习,总结如下:1、class 可以用来在模板中定义泛指类型(不推荐);2、typename 是可以消除模板中的二义性;3、try...catch 可以将函数体分成 2 部分;4、异常声明能够提供程序的可读性。

欢迎大家一起来学习 C++ 语言,可以加我QQ:243343083。

原文地址:http://blog.51cto.com/12810168/2125354

时间: 2024-10-12 07:29:52

令人迷惑的写法(五十六)的相关文章

第三百五十六节,Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy分布式爬虫要点

第三百五十六节,Python分布式爬虫打造搜索引擎Scrapy精讲-scrapy分布式爬虫要点 1.分布式爬虫原理 2.分布式爬虫优点 3.分布式爬虫需要解决的问题

Android笔记(五十六) Android四大组件之一——ContentProvider,实现自己的ContentProvider

有时候我们自己的程序也需要向外接提供数据,那么就需要我们自己实现ContentProvider. 自己实现ContentProvider的话需要新建一个类去继承ContentProvider,然后重写类中的的6个抽象方法. onCreate():初始化内容提供器时候会调用,通常会在这里完成对数据库的创建和升级等操作,返回true表示内容提供器初始化成功,返回false则表示失败,注意,只有当存在ContentResolver尝试访问我们程序中的数据时,内容提供其才会被初始化 query():从内

猫猫学iOS(五十六)网络基础以及如何搭建服务器

猫猫分享,必须精品 原创文章,欢迎转载.转载请注明:翟乃玉的博客 地址:http://blog.csdn.net/u013357243?viewmode=contents 一:为什么要学习网络编程 关于这个问题,为什么要学习网络编程,猫猫的理解就是,这东西是时代发展的必要,没什么为什么,就是应该学,除非你就是想玩单机,但是就算是单机也会有购买金币之类的网络需求,简单来说,有了网络,让你不再是一个人在战斗. 网络编程是一种实时更新应用数据的常用手段 . 网络编程是开发优秀网络应用的前提和基础. 总

第五十六条:遵守普遍接受的命名惯例

Java平台建立了一套很好的命名惯例(naming convention),其中有许多命名惯例包含在<The  Java  Language Specification>中. 不严格的讲,这些命名惯例分为两大类:字面的和语法的. 字面的命名惯例比较少,但也涉及包,类,方法,域和类型变量. 包的名称应该是层次状的,用"."分割每个部分.任何将在你的组织之外使用的包,其名称都应该以你的组织的Internet域名开头,并且将 顶级域名放在前面,例如com.sun ,gov.nsa

C#编程(五十六)----------可观察的集合ObservableCollection

原文链接: http://blog.csdn.net/shanyongxu/article/details/47080685 可观察的集合 如果需要集合中的元素核实删除或添加的信息,就可以使用ObservableCollection<T>类. ObservableCollection<T>类表示一个动态数据集合,在添加项,移除项或刷新整个列表时,刺激和将提供通知. 命名空间:System.Collections.ObjectModle 语法:public class Observa

第五十六节,python实现支持并发、断点续传的Ftp程序

一.要求 1.用户md5认证 2.支持多用户同时登陆(并发) 3.进入用户的命令行模式,支持cd切换目录,ls查看目录子文件 4.执行命令(ipconfig) 5.传输文件: a.支持断点续传 b.传输中显示进度条 二.思路 1.客户端用户登录和注册: a.客户端仅提供用户名和密码,选择登录或注册,b.服务器端进行注册并将加密后的密码写入文件,最后返回给客户端是否登录或注册成功 2.ls和cd命令 a.客户端输入命令,服务器端处理并返回给客户端 3.执行命令: a.客户端发送需要执行的命令b.服

一个屌丝程序猿的人生(五十六)

"蓟门桥西到了.请乘客有序上下车,下车请刷卡." 随着公交车上报音员的声音响起,公交车缓缓的停了下来. 林萧从公交车上下来,便直奔宿舍而去.方才在培训机构,林萧第一个离开了教室,这倒不是他自恃项目已经写完了,对张建接下来要讲的没有兴趣. 而是他已经想好了,该如何在这次项目中,达到一鸣惊人的效果,以至于他迫不及待的便离开了. 至于林萧想到的办法,简单的来说,就是两个字--质量. 其实林萧完全赶得上张建的学习速度,甚至可以比张建更快,之所以林萧在速度上落后了,实际上是由于他研究了很多,教学

五十六个民族

01.汉族 02.壮族 03.满族 04.回族 05.苗族 06.维吾尔族 07.土家族 08.彝族 09.蒙古族 10.藏族 11.布依族 12.侗族 13.瑶族 14.朝鲜族 15.白族 16.哈尼族 17.哈萨克族 18.黎族   19.傣族 20.畲族 21.傈僳族 22.仡佬族 23.东乡族 24.高山族 25.拉祜族 26.水族 27.佤族 28.纳西族 29.羌族 30.土族 31.仫佬族 32.锡伯族 33.柯尔克孜族 34.达斡尔族 35.景颇族 36.毛南族 37.撒拉族 3

第五十六课 云计算模型 openstack架构、keystone基础及部署

虚拟机及云计算模型介绍 OpenStack  Overview OpenStack  演示架构.Keystone基础及部署 Glance基础原理及部署应用