C++对象模型——Template中的名称决议方式 (第七章)

Template中的名称决议方式 (Name Resolution within a Template)

必须可以区分下面两种意义,一种是C++ Standard所谓的"sope of the template",也就是"定义出template"的程序.还有一种是C++ Standard所谓的"scope of the template instantiation",也就是"具现出template"的程序.

第一种情况例如以下所看到的:

// scope of the template definition
extern double foo(double);
template <class type>
class ScopeRules {
public:
    void invariant() {
        _member = foo(_val);
    }
    type type_dependent() {
        return foo(_member);
    }
    // ...
private:
    int _val;
    type _member;
};

另外一种情况例如以下所看到的:

// scope of the template instantiation
extern int foo(int);
// ...
ScopeRules<int> sr0;

在ScopeRules template 中有两个foo()调用操作.在"scope of template definition"中,仅仅有一个foo()函数声明位于scope内.然而在"scope of template instantiation"中,两个foo()函数声明都位于scope内,假设有一个函数调用操作:

// scope of the template instantiation
sr0.invariant();

那么在invariant()中调用的到底是哪一个foo()函数实体呢?

// 调用的哪一个foo()函数实体
_member = foo(_val);

在调用操作的那一点,程序中的两个函数实体是:

// scope of the template declaration
extern double foo(double);
// scope of the template instantiation
extern int foo(int);

而_val的类型是 int,那么选中的是哪一个呢?

结果选中的是直觉以外的那一个:

// scope of the template declaration
extern double foo(double);

Template中对于一个nonmember name的决议结果是依据这个name的使用是否与"用以具现出该template的參数类型"有关而决定的.假设其使用不相关,那么就以"scope of the template declaration"来决定name.假设其使用互有关联,那么就以"scope of the template instantiation"来决定name.在第一个样例中,foo()与用以具现ScopeRules的參数类型无关:

// the resolution of foo() is not dependent on the template argument
_member = foo(_val);

这是由于_val的类型是int;_val是一个"类型不会变动"的 template class member.也就是说,被用来具现出这个 template 的真正类型,对于_val的类型并没有影响.此外,函数的决议结果仅仅和函数的原型有关,和函数的返回值没有关联.因此,_member的类型并不会影响哪一个foo()实体被选中.foo()的调用与 template 參数毫无关联.所以调用操作必须依据"scope
of the template declaration"来决议.在此scope中,仅仅有一个foo()候选者.

以下是与类型相关的使用方法:

sr0.type_dependent();

这个函数的内容例如以下:

return foo(_member);

它到底会调用哪一个foo()呢?

这个样例非常清楚与 template 參数有关,由于该參数来决定_member的真正类型.所以这一次foo()必须在"scope of the template instantiation"中决议.

这意味着一个编译器必须保持两个scope contexts:

1."scope of the template declaration",用以专注于一般的 template class.

2."scope of the template instantiation",用以专注于特定的实体.

编译器的决议算法必须决定哪一个才是适当的scope,然后在当中搜寻适当的name.

Member Function的具现行为 (Member Function Instantiation)

对于 template 的支持,最困难的是 template function的具现.眼下的编译器提供两个策略:一个是编译时期策略,程序代码必须在program text file中备妥可用;还有一个是链接时期策略,有一些meta-complication工具能够导引编译器的具现行为.

以下是编译器设计者必须回答的三个主要问题:

1.编译器怎样找出函数的定义?

2.编译器怎样可以仅仅具现出用到的member functions?

3.编译器怎样阻止member definition在多个.o文件里都被具现呢?

 问题1:方法一是包括 template program text file,就好像它是个header文件一样.方法二是要求一个文件命名规则,比如能够要求在Point.h中发现的函数声明,其 template program text一定要放置于文件Point.c或Point.cpp中.

问题2:方法1就是忽略这个要求,把一个已经具现出的 class 的全部member functions都产生出来.方法二是仿真链接操作,检測看哪一个函数真正须要,然后仅仅为它产生实体.

问题3:方法1就是产生多个实体,然后从链接器中提供支持,仅仅留下当中一个实体,其余忽略.方法二是由使用者来导引"仿真链接阶段"的具现策略,决定哪些实体才是所须要的.

时间: 2024-07-31 14:24:35

C++对象模型——Template中的名称决议方式 (第七章)的相关文章

C++ template —— 模板中的名称(三)

第9章 模板中的名称------------------------------------------------------------------------------------------------------------C++(与C一样)是一种上下文相关语言:对于C++的一个构造,我们不能脱离它的上下文来理解它.模板也是一种构造,它必须处理多种上下文相关信息:(1)模板出现的上下文:(2)模板实例化的上下文:(3)用来实例化模板的模板实参的上下文. 9.1 名称的分类 主要的命名

表单提交中get和post方式的区别

表单提交中get和post方式的区别有5点 1.get是从服务器上获取数据,post是向服务器传送数据. 2.get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到.post是通过HTTPpost机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址.用户看不到这个过程. 3.对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Requ

使用Android中API建议的方式实现SQLite数据库的增、删、改、查的操作

package com.examp.use_SQLite.dao; import java.util.ArrayList; import java.util.List; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import com.examp

WCF中常用的binding方式

原文地址:http://www.cnblogs.com/Anima0My/archive/2008/04/16/1156146.html WCF中常用的binding方式: BasicHttpBinding: 用于把 WCF 服务当作 ASMX Web 服务.用于兼容旧的Web ASMX 服务.WSHttpBinding: 比 BasicHttpBinding 更加安全,通常用于 non-duplex 服务通讯.WSDualHttpBinding: 和 WSHttpBinding 相比,它支持 

spring -mvc 将对象封装json返回时删除掉对象中的属性注解方式

spring -mvc 将对象封装json返回时删除掉对象中的属性注解方式 在类名,接口头上注解使用在 @JsonIgnoreProperties(value={"comid"}) //希望动态过滤掉的属性 例 @JsonIgnoreProperties(value={"comid"}) public interface 接口名称{ } @JsonIgnoreProperties(value={"comid"}) public class 类名{

KendoUi控件kendoGrid中template中条件判断的使用

根据dataSource中提供的值渲染出来的页面效果如下: 最后一列的操作,根据是否已经处理来显示"回收"的操作按钮. 相关代码如下,主要是template中使用条件判断语句的方式: var kendoGridPermissionApplys = $("#kendo_grid_permission_applys").kendoGrid( { dataSource:{ data:<?php echo $test;?> }, sortable: true,

IOS开发之UI中开启动画的方式

UI中开启动画的方式 开启动画是UIImageView中的功能属性  有渐进式动画和序列帧动画 渐进式动画包括头尾式动画和block式动画 序列帧动画即为在极短时间内播放一组连续的图片所产生的动画效果 首先需要创建一个UIImageView对象为imageView1.序列帧动画基本步骤 将所要播放的图片数组赋值给UIImageView对象的animationImages属性,它就是一个数组对象 imageView.animationImages=array 设置动画的执行次数(animation

WCF中常用的binding方式 z

WCF中常用的binding方式: BasicHttpBinding: 用于把 WCF 服务当作 ASMX Web 服务.用于兼容旧的Web ASMX 服务. WSHttpBinding: 比 BasicHttpBinding 更加安全,通常用于 non-duplex 服务通讯. WSDualHttpBinding: 和 WSHttpBinding 相比,它支持 duplex 类型的服务. WSFederationHttpBinding: WS-Federation 安全通讯协议. NetTcp

类设计中几种继承方式

 通过继承能够从已有的类派生出新的类,而派生类继承了基类的特征,包括方法.正如继承一笔财产要比自己白手起家容易一样,通过继承派生出的类通常比设计新类要容易得多.下面是可以通过继承完成的一些工作. ①可以在已有类的基础上添加功能. ②可以给类添加数据. ③可以修改类方法的行为. C++有三种继承方式:公有继承.保护继承和私有继承. 一.公有继承 公有继承是最常用的方式,它建立一种is-a关系,即派生类对象也是一个基类对象,可以对基类对象执行的任何操作,也可以对派生类对象执行. ①公有继承不建立