- 浏览: 3047870 次
- 性别:
- 来自: 海外
文章分类
- 全部博客 (430)
- Programming Languages (23)
- Compiler (20)
- Virtual Machine (57)
- Garbage Collection (4)
- HotSpot VM (26)
- Mono (2)
- SSCLI Rotor (1)
- Harmony (0)
- DLR (19)
- Ruby (28)
- C# (38)
- F# (3)
- Haskell (0)
- Scheme (1)
- Regular Expression (5)
- Python (4)
- ECMAScript (2)
- JavaScript (18)
- ActionScript (7)
- Squirrel (2)
- C (6)
- C++ (10)
- D (2)
- .NET (13)
- Java (86)
- Scala (1)
- Groovy (3)
- Optimization (6)
- Data Structure and Algorithm (3)
- Books (4)
- WPF (1)
- Game Engines (7)
- 吉里吉里 (12)
- UML (1)
- Reverse Engineering (11)
- NSIS (4)
- Utilities (3)
- Design Patterns (1)
- Visual Studio (9)
- Windows 7 (3)
- x86 Assembler (1)
- Android (2)
- School Assignment / Test (6)
- Anti-virus (1)
- REST (1)
- Profiling (1)
- misc (39)
- NetOA (12)
- rant (6)
- anime (5)
- Links (12)
- CLR (7)
- GC (1)
- OpenJDK (2)
- JVM (4)
- KVM (0)
- Rhino (1)
- LINQ (2)
- JScript (0)
- Nashorn (0)
- Dalvik (1)
- DTrace (0)
- LLVM (0)
- MSIL (0)
最新评论
-
mldxs:
虽然很多还是看不懂,写的很好!
虚拟机随谈(一):解释器,树遍历解释器,基于栈与基于寄存器,大杂烩 -
HanyuKing:
Java的多维数组 -
funnyone:
Java 8的default method与method resolution -
ljs_nogard:
Xamarin workbook - .Net Core 中不 ...
LINQ的恶搞…… -
txm119161336:
allocatestlye1 顺序为 // Fields o ...
最近做的两次Java/JVM分享的概要
忘了……模板啊忘光了 T T
今天有同学考C++,后来问了我一个问题:要写一个Set类,支持拷贝构造函数、+=、-=、=、<<等运算符的重载。我偷懒用std::list<T>给实现了一个版本,因为那题目貌似原本有要求用链表来实现(但却没说那链表一定要自己实现,OTL),而且直接用STL的set<T>也未免太“没诚意”了,呵呵
但遇到了点小问题:
我想直接把std::list<T>::iterator用作Set<T>的iterator,但是怎么编译都不行,说std::list<T>不是Set<T>的派生类什么的。然后我就严重被郁闷了……
问了axx大才知道原来在std::list<T>::iterator前加上typename关键字就行了。因为std::list<T>在实例化之前,编译器没办法判断iterator到底是成员还是类型,所以会出错。
于是代码就像这样(别笑,大家都是为了偷懒……本来给集合定义一个顺序迭代器也是够怪的,不过不想自己实现内部用的链表啊):
set.h
注意13、14、68行里typename的使用。
main.cpp
axx大提到还有一个using declaration可以用于从基类把名字引入到派生类的作用域中,嗯这个我也印象模糊了……
C++真是……我还是写得太少了。平时还是应该多写点的
今天有同学考C++,后来问了我一个问题:要写一个Set类,支持拷贝构造函数、+=、-=、=、<<等运算符的重载。我偷懒用std::list<T>给实现了一个版本,因为那题目貌似原本有要求用链表来实现(但却没说那链表一定要自己实现,OTL),而且直接用STL的set<T>也未免太“没诚意”了,呵呵
但遇到了点小问题:
我想直接把std::list<T>::iterator用作Set<T>的iterator,但是怎么编译都不行,说std::list<T>不是Set<T>的派生类什么的。然后我就严重被郁闷了……
问了axx大才知道原来在std::list<T>::iterator前加上typename关键字就行了。因为std::list<T>在实例化之前,编译器没办法判断iterator到底是成员还是类型,所以会出错。
于是代码就像这样(别笑,大家都是为了偷懒……本来给集合定义一个顺序迭代器也是够怪的,不过不想自己实现内部用的链表啊):
set.h
#ifndef SET_H_INCLUDED #define SET_H_INCLUDED #include <list> #include <iostream> #include <algorithm> template<typename T> class Set { std::list<T> m_data; public: typedef typename std::list<T>::iterator iterator; typedef typename std::list<T>::const_iterator const_iterator; Set( ) { } Set( T array[], T count ) { for (T i = 0; i < count; ++i) { m_data.push_back( array[ i ] ); } m_data.unique( ); } Set( const Set<T>& rhs ) { if ( &rhs == this ) return; m_data.clear( ); m_data = rhs.m_data; } Set<T>& operator =( const Set<T>& rhs ) { if ( &rhs == this ) return *this; m_data.clear( ); m_data = rhs.m_data; return *this; } Set<T>& operator +=( const T& value ) { if ( std::find( m_data.begin( ), m_data.end( ), value ) == m_data.end( ) ) { m_data.push_back( value ); } return *this; } Set<T>& operator -=( const T& value ) { m_data.remove( value ); return *this; } iterator begin( ) { return m_data.begin( ); } iterator end( ) { return m_data.end( ); } const_iterator begin( ) const { return ((const std::list<T>&)m_data).begin( ); } const_iterator end( ) const { return ((const std::list<T>&)m_data).end( ); } friend std::ostream& operator <<( std::ostream& out, const Set<T>& set ) { out << "["; typename Set<T>::const_iterator it = set.begin( ); if ( it != set.end( ) ) { out << *it++; if ( it != set.end( ) ) { for ( ; it != set.end( ); ++it ) { out << ", " << *it; } } } out << "]"; return out; } }; #endif // SET_H_INCLUDED
注意13、14、68行里typename的使用。
main.cpp
#include <iostream> #include "set.h" using namespace std; int main() { int a[] = { 1, 3, 5, 7, 9 }; int x = 2, y = 3; Set<int> s1( a, 5 ); Set<int> s2; s1 += x; s2 = s1; s2 -= y; cout << s1 << endl << s2 << endl; return 0; }
axx大提到还有一个using declaration可以用于从基类把名字引入到派生类的作用域中,嗯这个我也印象模糊了……
C++真是……我还是写得太少了。平时还是应该多写点的
发表评论
-
字符串的一般封装方式的内存布局 (0): 拿在手上的是什么
2013-11-04 18:22 21489(Disclaimer:未经许可请 ... -
字符串的一般封装方式的内存布局
2013-11-01 12:55 0(Disclaimer:未经许可请 ... -
关于string,内存布局,C++ std::string,CoW
2013-10-30 20:45 0(Disclaimer:未经许可请 ... -
struct做参数不能从寄存器传?
2013-08-28 23:33 0test test test struct Foo { i ... -
[入门级] 使用inline函数的陷阱
2011-04-21 22:39 0xxx.hpp xxx.inline.hpp inline ... -
C++的vtable的name mangling
2011-04-21 21:53 0_ZTV 开头 -
C++里用typedef struct...
2010-06-12 14:42 3887今天要写个东西,参照的一段C++代码里看到了诡异的东西,形式类 ... -
C++的虚方法调用的开销
2010-01-10 02:53 0不只是从vftbl找到函数指针那么简单而已。因为C++支持多继 ... -
C++求值顺序
2009-12-12 23:16 0呵呵,有个例子总是形 ... -
__fastcall由callee做栈平衡
2009-10-14 01:51 0#include <iostream> usin ... -
typedef...
2009-06-16 21:22 0原来函数指针能这样用的啊……原来typedef不只可以用来声明 ... -
拿vtable来玩玩
2009-06-04 03:53 0#include <iostream> usin ... -
从1加到N……我败了
2009-05-11 10:06 0有人提到Python比C++优越因为代码短而简洁,并举例说1加 ... -
delete NULL会怎样?
2009-04-22 10:03 8104原文在此:Can you delete a NULL poin ... -
Boost 1.35.0
2008-06-25 04:45 0Boost C++ Library Version 1.35. ... -
确定性析构在有指针的环境下的麻烦之处
2008-05-16 11:26 2624刚考完大软,心里还在 ... -
又是宏……do..while(0)的用法
2008-05-04 20:24 4668真是的,我用C++还是太少了。这个宏以前明明见过的,但其存在的 ... -
火星了,今天才知道C++0x也通过了lambda表达式/闭包的提案
2008-04-16 19:31 3078如题。我总是后知后觉诶。不过这提案有意思…… 之前我在C#与 ... -
将ANTLR生成的.tokens文件重格式化(C++版)
2008-03-28 02:02 2458相关链接: 将ANTLR生成的.tokens文件重格式化(Ru ... -
奇怪的宏
2007-11-05 22:19 2113我C++确实不怎么样,不过近来不得不再唤醒那远古的记忆……即使 ...
相关推荐
如果一个名称是嵌套在模板类型参数内部的,并且是依赖于模板参数的,那么在引用这个名称时,就需要使用`typename`关键字来明确指出这是一个类型名称。例如: ```cpp template <typename Iterator> struct iterator_...
在定义模板时,我们常常会遇到`typename`和`class`这两个关键字,它们在模板声明中扮演着重要的角色。本文将深入探讨这两个关键字的含义和用法。 ### 1. `typename` 关键字 `typename`关键字在模板中用于声明依赖...
为了告诉编译器`T::const_iterator`是一个类型,我们需要使用`typename`关键字: ```cpp template <typename T> void add(const T& container, T& sum) { typename T::const_iterator iter = container.begin(); ...
本文将深入探讨`typename`的作用、使用场景及其与`class`关键字的区别。 首先,`typename`和`class`在声明模板类型参数时是等价的。如以下模板声明所示: ```cpp template<class T> class Widget; template...
asm auto bad_cast bad_typeid bool break case catch char class const const_cast continue default delete do double dynamic_cast ...typedef typeid typename union unsigned using virtual void volatile while
在深入探讨C++中`typename`关键字的双层含义之前,我们先来简要回顾一下C++模板的基础知识。模板是C++的一项强大特性,它允许程序员编写泛型代码,即能够处理不同类型数据的代码。这极大地提高了代码的重用性和灵活...
- **功能**:`case`关键字与`switch`语句结合使用,为不同的值指定不同的执行路径。 - **用法**:每个`case`标签后跟一个具体的值和对应执行的代码块。 #### catch(捕获异常) - **功能**:`catch`用于捕获抛出的...
例如,`template <typename T> class A { ...; };`这里声明了一个名为A的模板。 11. throw:throw是C++中的一种关键字,用于抛出一个异常。例如,`throw std::runtime_error("Error");`这里抛出一个异常。 12. try:...
// 使用typename关键字 LengthType length = myArr.GetLength(); } ``` 在这里,`typename` 关键字至关重要,因为它指示`T::LengthType`是一个类型,而不是成员变量或成员函数。如果没有`typename`,编译器将无法...
根据标题"Why C++ Supports typename and class"以及描述中提到的“不错的关于C++中typedef和class的使用说明”,我们可以详细分析这两个关键词在C++中的作用和历史背景。 ### `typename`与`class`:模板参数的指示...
C++关键字大全(67个) asm auto bad_cast bad_typeid bool break case catch char class const const_cast continue default delete do double dynamic_cast else enum except explicit extern false finally float ...
* typeid和typename关键字的区别 二、运算符 * 算术运算符:+、-、\*、/、%等 *比较运算符:==、!=、>、<、>=、等 * 逻辑运算符:&&、||、!等 *赋值运算符:=、+=、-=、\*=、/=、%=等 三、控制结构 * 顺序结构:...
答:class用于定义类,在模板引入c++后,初定义模板的方法为:template,这里class关键字表明T是一个类型,后来为了避免class在这两个地方的使用可能给人带来混淆,所以引入了typename这个关键字,它的作用同...
在C++中,关键字具有特殊的含义,它们不能作为标识符(如变量名、函数名)使用。以下是一些C++的关键字及其用途的详细解释: 1. `asm`: 这个关键字在早期的C++中用于嵌入汇编代码,但已被`__asm`替代。然而,现代...
使用class关键字声明一个类。 9. const:常量的,constant所修饰的对象或变量不能被改变,修饰函数时,该函数不能改变在该函数外面声明的变量也不能调用任何非const函数。 10. const_cast:用法:const_cast...
正确使用`typename`关键字可以确保代码在不同编译器和标准下都能正常工作。 总结来说,`class`和`typename`在C++模板中并非完全可互换。`class`主要用于声明类,而`typename`则用于指示模板中的从属类型是类型名称...
6. typename关键字 在模板中,`typename`关键字用于告诉编译器某个表达式是一个类型名称,特别是在依赖于模板参数的表达式中。例如,当访问模板参数类的成员时,如果成员是一个类型,我们需要使用`typename`关键字...
C++是一种强大的面向对象的编程语言,其语法丰富...这些关键字是C++语言的基础,理解和正确使用它们是编写高效、可靠代码的关键。通过熟练掌握这些关键字,开发者可以充分利用C++提供的强大功能,实现复杂的程序设计。