C++进阶--模板及关键字typename

//############################################################################
/*
 *  模板介绍
 */
//函数模板
template<typename T>
T square(T x) {
   return x*x;
}

//类模板
template<typename T>
class BoVector {
   T arr[1000];
   int size;
public:
   BoVector():size(0) {}
   void push(T x) { arr[size] = x; size++; }
   T get(int i) const { return arr[i]; }
   int getSize() const { return size; }
   //void print() const {for(int i=0; i<size; i++) {cout << arr[i] << endl;}}
   void print() const {
      const int* p = arr;
      for(int i=0;  i<size; i++) {cout << *(p++) << endl;}
   }
};

template<typename T>
BoVector<T> operator*(const BoVector<T>& rhs1, BoVector<T>& rhs2) {
   BoVector<T> ret;
   for (int i=0; i<rhs1.getSize(); i++) {
      ret.push(rhs1.get(i)*rhs2.get(i));
   }
   return ret;
}

int main()
{
   cout << square(5) << endl;

   BoVector<int> bv;
   bv.push(2);
   bv.push(5);
   bv.push(8);
   bv.push(9);
   bv.print();

   cout << "Print squared bv: " << endl;
   bv = square(bv);
   bv.print();
}

//############################################################################
/*
 *  函数模板类型省略
 */

template<class T>
void f() {
   ...
}

int main() {
   f<int>();  // T显式指定
}

// 类型T可以省略
template<class T>
void f(T t) {
   ...
}

int main() {
   f(67);  // 编译将其绑定为int型

   f<long>(67);  // 显示告诉编译器为long类型

   f(67L);
}

//############################################################################
/*
 * 关键字typename及其用法
 */

template<class T>
void printAge(T& item) {
   ...
}

template<typename T>
void printAge(T& item) {
   ...
}

//用于模板参数两者等效
//使用typename更易理解
//

/*
 * Dependent Type 取决于模板参数的类型
 */
template<typename T> A {
   vector<T> vec;
}

/*
 * Nested Dependent Type  包含在某个类里的dependent type
 */
template<typename T> A {
   T::age myAge = 9;
   vector<T>::iterator itr;
}

/*
 * typename 用法二
 */
class Dog {
   public:
   typedef int age;
};

template<class T>
void printMyAge(T& item) {
   int n = 9;
   T::age* a = &n;
   cout << (*a) << endl;
}

int main() {
   Dog d;
   printMyAge<Dog>(d);
}

// 上面的代码编译不过,T::age是类型,编译器当成变量

//class Wolf {
//   public:
//   int age;
//}; 

/*
 * 法则: 当使用嵌套依赖类型的时候总是在前面加上typename,告诉编译器这是类型
 */

// 例外: 在基类列表或者初始化列表中

template<typename T>
class D : public T::NestedBaseClass {
public:
   D(int x) : T::NestedBaseClass(x) {
      typename T::NestedBaseClass y;
      ...
   }
}

//############################################################################
/*
 *  模板特化和偏特化
 */
// std是一个特殊的命名空间,我们不能更改它的内容,但是可以为我们的类型提供特化的版本

原文地址:https://www.cnblogs.com/logchen/p/10182696.html

时间: 2024-10-17 21:39:26

C++进阶--模板及关键字typename的相关文章

C++ Primer 学习笔记_45_模板(三):缺省模板参数(借助标准模板容器deque实现Stack模板)、成员模板、关键字typename

一.缺省模板参数 1.stack内存能否借助标准模板容器管理呢?答案是肯定的,只需要多传一个模板参数即可,而且模板参数还可以是缺省的,如下: template <typename T, typename CONT = std::deque<T> > //此处末尾必须有空格,否则编译出错 class Stack { - private: CONT c_; }; 如果没有传第二个参数,默认为deque 双端队列,当然我们也可以传递std::vector<T> 2.示例:借助

C++ - 模板(template)中typename的使用方法

声明template参数时, 前缀关键字class和typename可以互换; 使用关键字typename标识嵌套从属类型名称, 但不需在基类列表和成员初始化列表内使用. 从属名称(dependent names): 模板(template)内出现的名称, 相依于某个模板(template)参数, 如T t; 嵌套从属名称(nested dependent names):从属名称在class内呈嵌套装, 如T::const_iterator ci; 非从属名称(non-dependent nam

转载:模板(template)中typename的使用方法

声明template参数时, 前缀关键字class和typename可以互换; 使用关键字typename标识嵌套从属类型名称, 但不需在基类列表和成员初始化列表内使用. 从属名称(dependent names): 模板(template)内出现的名称, 相依于某个模板(template)参数, 如T t; 嵌套从属名称(nested dependent names):从属名称在class内呈嵌套装, 如T::const_iterator ci; 非从属名称(non-dependent nam

进阶Kotlin-常见关键字

常见Kotlin 的关键字   一些常见的语法,我没有写注释. 前面基础的kotlin语法已经弄完了. 现在是高阶kotlin的语法啊. 包括,面向对象,lambad等. 其中面向对象的三大特点:封装 继承 多态 lambad基础使用 集合和字典等 关键字 解释 关键字 解释 if for while when else break continue 返回最近层循环体 do class 类 fun 函数 package 包 interface 接口 public 公开 private 私有 pr

Java——面向对象进阶(final关键字,static关键字,匿名对象,内部类,包的声明与访问,四种访问修饰符,代码块)

一.final关键字 继承的出现提高了代码的复用性,并方便开发.但随之也有问题,有些类在描述完之后,不想被继承,或者有些类中的部分方法功能是固定的,不想让子类重写.可是当子类继承了这些特殊类之后,就可以对其中的方法进行重写,那怎么解决呢? 要解决上述的这些问题,需要使用到一个关键字final,final的意思为最终,不可变.final是个修饰符,它可以用来修饰类,类的成员,以及局部变量. 1.修饰类 被final修饰的类不可以被继承,但是可以继承其他类. class Yy {} final cl

C++进阶--命名空间和关键字using

//############################################################################ /* * C++关键字:using * * 1. using指示: 将命名空间所以成员引入当前作用域 * 例子: */ using namespace std; /* 2. using声明 * a. 将一个特定命名空间成员引入当前作用域 * b. 将一个成员从基类引入当前类的作用域 * 例子: */ using std::cout; cou

Java进阶(6) - 并发(关键字)

并发的特性1.可见性a. 保证任何一个线程修改变量立即写入到主内存中(堆):b. 所有线程对该变量引用会强制立即失效,并且该线程必须去堆中获取最新的变量值. 2.指令重排序代码的执行顺序 会在JVM中(编译器优化 指令级并行重排序 内存系统重排序 最终执行的指令序列) 3.原子性同一时刻最多只有一个线程访问该段代码. Volatile -> 可见性.指令重排序 Synchronied -> 可见性.指令重排序.原子性 lock存在价值synchronized只在以下2种情况下会释放锁1)获取锁

C++ chapter 10——模板

**模板的概念 函数模板 类模板 名空间** 一.模板的概念 C++的模板提供对逻辑结构相同的数据对象通用行为的定义.模板运算对象的类型不是实际的数据类型,而是一种参数化的类型. 一个带类型参数的函数称为函数模板,一个带类型参数的类称为类模板. 二.函数模板 1.函数模板的概念 函数模板的基本原理是通过数据类型的参数化,将一组算法相同但所处理数据类型不同的重载函数凝练成一个函数模板.编译时,再由编译器按照函数模板自动生成针对不同数据类型的重载函数定义代码. 使用函数模板.对于函数模板,数据类型本

C++学习笔记之模板(1)——从函数重载到函数模板

一.函数重载 因为函数重载比较容易理解,并且非常有助于我们理解函数模板的意义,所以这里我们先来用一个经典的例子展示为什么要使用函数重载,这比读文字定义有效的多. 现在我们编写一个交换两个int变量值得函数,可以这样写: 1 void swap(int & a, int & b) 2 { 3 int tmp; 4 5 tmp = a; 6 a = b; 7 b = tmp; 8 9 } 假如我们现在想在与上面函数相同的文件中(可以理解为同一个main函数中)交换两个float变量呢,是不是需