C++模板 静态成员 定义(实例化)
问一个问题:
考虑一个模板:
template <typename T> class Test{
public:
static std::string info;
};
对于下面若干种定义方式。哪些是对的(通过编译)?
template <> string Test<int>::info("123");
template <typename T> string Test<T>::info("123");
template <typename T> string Test<T>::info;
template <> string Test<int>::info;
template <> string Test<int>::info();
template <typename T> string Test<T>::info();
为了不影响大家分析推断,我把答案颜色调成比較浅的颜色,以下即是答案:
- template <> string Test<int>::info("123");//ok
- template <typename T> string Test<T>::info("123");//ok
- template <typename T> string Test<T>::info;//ok
- template <> string Test<int>::info; //error
- template <> string Test<int>::info();//error
- template <typename T> string Test<T>::info();//error
问题解答:
首先,说明一下三个正确的答案。
第一种形式称之为特化定义,其作用是为模板某一特化提供其静态成员的定义,在我们样例中,它只为Test<int>类的静态成员info提供定义。而且调用单參数构造函数初始化。
另外一种形式类似于普通类的静态成员的定义方式,其作用是隐式地在该编译单元为模板的全部特化提供其静态成员的定义,在我们样例中,在首次使用Test<int>,Test<float>,Test<char>...会隐式提供静态成员的定义,而且调用单參数构造函数初始化。
第三种形式和另外一种形式一致,唯一不同就是採用默认构造函数初始化。
其次。说明一下三个错误的答案。
第一种形式。非常多人都会觉得是对的。觉得它採用默认构造函数初始化。但编译器会对特化定义进行特殊处理,编译觉得它是一个声明而非定义。至于为什么如此,应该询问一下制定标准的人。我觉得可能实现这种语法可能比較困难而且这个语法也比較鸡肋。
另外一种形式,这不成了声明一个函数啦。
第三种形式。同另外一种。
很多其它内容:
两种正确的定义方式还有哪些其它的差别呢?
//a.cpp
template <typename T> string Test<T>::info("4321");
能够使用Test<int>::info
//b.cpp
template <typename T> string Test<T>::info("1234");
也能够使用Test<int>::info
这两个定义能够在不同的编译单元共存。Test<int>::info的初始值是多少,这取决与静态成员的初始化顺序,所以这不是件好事。
//a.cpp
template <> string Test<int>::info("123");
//b.cpp
template <> string Test<int>::info("123");
而特化定义,上述方式无法通过编译。
//a.cpp
template <> string Test<int>::info("123"); //b.cpp
template <typename T> string Test<T>::info("123"); 一旦使用Test<int>::info无法通编译
上述方式无法通过编译。
一般为了避免无法编译,应当尽量降低使用,例如以下方式的定义
template <typename T> string Test<T>::info;
仅仅有在你首次须要使用时在实现文件里给出例如以下特化定义就可以,其它文件仅仅要包括头文件就能使用。
template <> string Test<int>::info("123");
应用案例:
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ #ifndef ANDROID_UTILS_SINGLETON_H
#define ANDROID_UTILS_SINGLETON_H #include <stdint.h>
#include <sys/types.h>
#include <utils/threads.h>
#include <cutils/compiler.h> namespace android {
// --------------------------------------------------------------------------- template <typename TYPE>
class ANDROID_API Singleton
{
public:
static TYPE& getInstance() {
Mutex::Autolock _l(sLock);
TYPE* instance = sInstance;
if (instance == 0) {
instance = new TYPE();
sInstance = instance;
}
return *instance;
} static bool hasInstance() {
Mutex::Autolock _l(sLock);
return sInstance != 0;
} protected:
~Singleton() { };
Singleton() { }; private:
//禁止复制构造函数和赋值运算符函数,禁止类外部和内部以及友元调用 declare private,not define
Singleton(const Singleton&);
Singleton& operator = (const Singleton&);
static Mutex sLock;
static TYPE* sInstance;
}; /*
* use ANDROID_SINGLETON_STATIC_INSTANCE(TYPE) in your implementation file
* (eg: <TYPE>.cpp) to create the static instance of Singleton<>'s attributes,
* and avoid to have a copy of them in each compilation units Singleton<TYPE>
* is used.
*
* NOTE: we use a version of Mutex ctor that takes a parameter, because
* for some unknown reason using the default ctor doesn't emit the variable! 特化定义必须使用有參数的构造函数,否则觉得是声明。
*/
//想要使用Singleton,须要在自己定义类型的实现文件里包括此宏,用以初始化类模版static变量,并显示实例化类模版
#define ANDROID_SINGLETON_STATIC_INSTANCE(TYPE) \
template<> Mutex Singleton< TYPE >::sLock(Mutex::PRIVATE); \ 特化定义
template<> TYPE* Singleton< TYPE >::sInstance(0); \ 特化定义
template class Singleton< TYPE >; \显示实例化 // ---------------------------------------------------------------------------
}; // namespace android
版权声明:本文博主原创文章,博客,未经同意不得转载。
C++模板 静态成员 定义(实例化)的更多相关文章
- [转]C++ 模板 静态成员 定义(实例化)
提出问题: 如果有这样一个模板: template <typename T> class Test{ public: static std::string info; }; 对于以下若干种 ...
- C++ Primer 学习笔记_77_模板与泛型编程 --实例化
模板与泛型编程 --实例化 引言: 模板是一个蓝图,它本身不是类或函数.编译器使用模板产生指定的类或函数的特定版本号.产生模板的特定类型实例的过程称为实例化. 模板在使用时将进行实例化,类模板在引用实 ...
- 读书笔记 effective c++ Item 46 如果想进行类型转换,在模板内部定义非成员函数
1. 问题的引入——将operator*模板化 Item 24中解释了为什么对于所有参数的隐式类型转换,只有非成员函数是合格的,并且使用了一个为Rational 类创建的operator*函数作为实例 ...
- C++模板显式实例化,隐式实例化,特化(具体化,偏特化)辨析
最近再次看C++ PRIMER PLUS的时候看到这个部分感觉讲得很烂,前后口径不一致,所以写个辨析让自己明白的同时也希望对此不太清楚的朋友能搞懂. 总结一下,C++只有模板显式实例化(explici ...
- C++ 模板的编译 以及 类模板内部的实例化
在C++中.编译器在看到模板的定义的时候.并不马上产生代码,仅仅有在看到用到模板时,比方调用了模板函数 或者 定义了类模板的 对象的时候.编译器才产生特定类型的代码. 一般而言,在调用函数的时候,仅仅 ...
- c/c++模板的定义和实现分开的问题及其解决方案
注意c/c++模板的定义和实现- - 定义一个类一般都是在头文件中进行类声明,在cpp文件中实现,但使用模板时应注意目前的C ...
- Ext.net Calendar 控件在有模板页的时候,模板页定义了TD的样式造成日历控件的样式丢掉
Ext.net Calendar 控件在有模板页的时候,模板页定义了TD的样式造成日历控件的样式丢掉 解决方案 在本页面添加下面的样式 <style type="text/css&qu ...
- template <typename T>模板类定义
#include "stdafx.h"#include "iostream"#include <ctime>using namespace std; ...
- c++模板使用及实现模板声明定义的分离
c++模板是编译器构造具体实例类型的模型,使类型参数化,是泛型编程的基础,泛型就是独立于特定类型. 一.模板分为函数模板和类模板两种. 函数模板:template <class 形参名,clas ...
随机推荐
- ASP.net gridview控件RowEditing,RowUpdating,RowDeleting,RowCancelingEdit事件的触发
一.说明 在gridview中删除和更新行是常用的操作,RowEditing,RowUpdating,RowDeleting,RowCancelingEdit等事件是删除更新对应的事件.如果想要使用自 ...
- 五种常见的ASP.NET应用程序安全缺陷
下面给出了五个例子,阐述如何按照上述建议增强应用程序的安全性.这些例子示范了代码中可能出现的缺陷,以及它们带来的安全风险.如何改写最少的代码来有效地降低攻击风险.1 篡改参数◎ 使用ASP.NET域验 ...
- redis的备份和恢复
Redis 数据备份与恢复 数据备份 语法 redis Save 命令基本语法如下: redis > SAVE 实例 redis > SAVE OK 该命令将在 redis 备份目录中创建 ...
- C# 如何获取错误所在行数
两种方法,一种是利用error.StackTrace,另外一种是try-catch找到错误行数,具体如下: 一.error.StackTrace代码 int i = ex.StackTrace.Ind ...
- POJ 1002 - 487-3279 STL
先把不是标准格式的字符串变成标准格式再输出出现两次以上的标准串和出现的次数不然输出 "No duplicates." #include <iostream> #incl ...
- POJ 1286 Necklace of Beads(项链的珠子)
Necklace of Beads Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 7874 Accepted: 3290 ...
- C#数组的指定位置复制函数
1. // 源数组 - 起始位置 -目的数组 - 起始位置 - 长度 System.Array.Copy(mcu_data, 2, read_mcu_data_whole, 0, mcu_data.L ...
- 【劳动节江南白衣Calvin 】我的后端开发书架2015
自从技术书的书架设定为”床底下“之后,又多了很多买书的空间.中国什么都贵,就是书便宜. 不定期更新,在碎片化的阅读下难免错评. 书架主要针对Java后端开发,书单更偏爱那些能用简短流畅的话,把少壮不努 ...
- R语言画正弦曲线
正弦曲线一个周期是2π,我们要先生成x的取值范围. 可以用seq函数生成一个等差序列,步进为0.01 x=seq( 0, 2*pi, 0.01 ) pi表示π y=sin(x) plot(x, ...
- HTML5 例子学习 HT 图形组件
HTML5 例子学习 HT 图形组件 HT 是啥:Everything you need to create cutting-edge 2D and 3D visualization. 这口号是当年心 ...