博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++模板 静态成员 定义(实例化)
阅读量:6317 次
发布时间:2019-06-22

本文共 4583 字,大约阅读时间需要 15 分钟。

问一个问题:

考虑一个模板:

template 
class Test{public: static std::string info;};
对于下面若干种定义方式。哪些是对的(通过编译)?

template <> string Test
::info("123");template
string Test
::info("123");template
string Test
::info;template <> string Test
::info; template <> string Test
::info();template
string Test
::info();
为了不影响大家分析推断,我把答案颜色调成比較浅的颜色,以下即是答案:

  1. template <> string Test<int>::info("123");//ok
  2. template <typename T> string Test<T>::info("123");//ok
  3. template <typename T> string Test<T>::info;//ok
  4. template <> string Test<int>::info; //error
  5. template <> string Test<int>::info();//error
  6. template <typename T> string Test<T>::info();//error

问题解答:

首先,说明一下三个正确的答案。

第一种形式称之为特化定义,其作用是为模板某一特化提供其静态成员的定义,在我们样例中,它只为Test<int>类的静态成员info提供定义。而且调用单參数构造函数初始化。

另外一种形式类似于普通类的静态成员的定义方式,其作用是隐式地在该编译单元为模板的全部特化提供其静态成员的定义,在我们样例中,在首次使用Test<int>,Test<float>,Test<char>...会隐式提供静态成员的定义,而且调用单參数构造函数初始化。

第三种形式和另外一种形式一致,唯一不同就是採用默认构造函数初始化。

其次。说明一下三个错误的答案。

第一种形式。非常多人都会觉得是对的。觉得它採用默认构造函数初始化。但编译器会对特化定义进行特殊处理,编译觉得它是一个声明而非定义。至于为什么如此,应该询问一下制定标准的人。我觉得可能实现这种语法可能比較困难而且这个语法也比較鸡肋。

另外一种形式,这不成了声明一个函数啦。

第三种形式。同另外一种。

很多其它内容:

两种正确的定义方式还有哪些其它的差别呢?

//a.cpptemplate 
string Test
::info("4321");能够使用Test
::info//b.cpptemplate
string Test
::info("1234");也能够使用Test
::info

这两个定义能够在不同的编译单元共存。Test<int>::info的初始值是多少,这取决与静态成员的初始化顺序,所以这不是件好事。

//a.cpptemplate <> string Test
::info("123");//b.cpptemplate <> string Test
::info("123");

 
而特化定义,上述方式无法通过编译。

//a.cpptemplate <> string Test
::info("123");//b.cpptemplate
string Test
::info("123");一旦使用Test
::info无法通编译
上述方式无法通过编译。

一般为了避免无法编译,应当尽量降低使用,例如以下方式的定义

template 
string Test
::info;
仅仅有在你首次须要使用时在实现文件里给出例如以下特化定义就可以,其它文件仅仅要包括头文件就能使用。

template <> string Test
::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 
#include
#include
#include
namespace android {// ---------------------------------------------------------------------------template
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:
.cpp) to create the static instance of Singleton<>'s attributes, * and avoid to have a copy of them in each compilation units Singleton
* 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陷阱与缺陷的学习笔记
查看>>
并发异步处理队列 .NET 4.5+
查看>>
VS2012下基于Glut OpenGL glScissor示例程序:
查看>>
xcode多target
查看>>
基于Log4net插件
查看>>
如何设计一门语言(七)——闭包、lambda和interface
查看>>
关于JAVA的参数列表传值的问题
查看>>
paip.按键替换映射总结
查看>>
Sharepoint学习笔记—习题系列--70-573习题解析 -(Q63-Q65)
查看>>
项目源码分享之[条码扫描后台监控程序]
查看>>
关于 HTML5 的 11 个让人难以接受的事实
查看>>
IIS 配置
查看>>
C# toolstrip 上添加DateTimePicker Control控件
查看>>
2013年7月31日
查看>>
How Tomcat Works(十一)
查看>>
Socket桥(转载)
查看>>
SharePoint 如何找到List的Template ID
查看>>
(二十三)原型模式详解(clone方法源码的简单剖析)
查看>>
ZOJ 1423 (Your)((Term)((Project))) (模拟+数据结构)
查看>>
AppBox升级进行时 - 拥抱Entity Framework的Code First开发模式
查看>>