模板中class与typename的辨析

目录

引言:

在声明类时

在定义模板时

模板定义中

依赖类型名称

示例


引言:

在C++编程语言中,typenameclass这两个关键字在许多情况下是可以互换使用的,但它们也有一些特定的用途和含义上的差异。那什么时候该用class,什么时候该用typename呢?

在声明类时

class MyClass {
    // ...
};

typename MyClass2 {
    // ...
};

尽管技术上允许使用typename来声明类,但在实际编码实践中,几乎总是使用class来声明类,因为这是C++的传统用法,并且更符合语言的习惯。

在定义模板时

在定义模板时,都可以用来声明模板参数作为类型。以下typename与class都可以。

template<typename T>
void function(T param) {
    // ...
}

typename告诉编译器T是一个类型参数。在C++98标准之前,这是必须的,以区别于非类型模板参数。然而,在C++11及以后的版本中,你可以在模板参数列表中使用class来代替typename。

在有些情况中,只能使用typename,而不能使用class。以下是需要使用typename替换class的情况

模板定义中

当在模板定义内部使用一个依赖于模板参数的类型时,通常需要在该类型前面加上typename关键字,以指示它是一个类型名,而不是静态成员变量或者其它非类型实体。

template <typename T>
class Example {
public:
    typename T::SubType* ptr; // 这里需要typename,因为SubType依赖于模板参数T
};

(当我们使用静态成员变量时,不需要在前面加上typename关键字,因为静态成员变量不是类型。相反,应该直接使用类名和作用域解析运算符::来访问静态成员变量)

依赖类型名称

在一个模板内部,如果你引用一个依赖于模板参数的类型名称(即嵌套依赖类型),你需要使用typename来明确指出这是一个类型。

template <typename T>
void function() {
    typename T::NestedType var; // typename用于指示NestedType是T的一个类型
}

示例

例1:

在下述代码中,我们想要完成list<int>类型的打印工作。

	void print_list(const list<int>& lt)
	{
		list<int>::const_iterator it = lt.begin();
		while (it != lt.end())
		{
			//*it = 10;
			cout << *it << " ";
			++it;
		}
		cout << endl;

		for (auto e : lt)
		{
			cout << e << " ";
		}
		cout << endl;
	}

        list<int>::const_iterator it = lt.begin();对于这句代码,list<int>已经点名了数据类型是什么,不需要用typename。

例2:

当我们想要同时满足打印其他类型时(list<string>),这时候就无法完成任务,因此我们可以借助模板函数完成。


	template<typename t>
	//template<class t>
	void print_list(const list<t>& lt)
	{

		typename list<t>::const_iterator it = lt.begin();
		while (it != lt.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
	}

 list<t>未实例化的类模板,编译器不能去他里面去找编译器就无法分别list<t>::const_iterator是内嵌类型,还是静态成员变量前面加一个typename就是告诉编译器,这里是一个类型,等list<t>实例化再去类里面去取。

当然,成功实现该功能还得益于,string类型完成了流插入的重载。

例3:

当我们想要再满足可以打印其他容器的内容时(vector(string)),这时候就在需要进行一次修改。

将模板参数t修改为容器参数。

        typename Container::const_iterator it = con.begin();

	template<typename Container>
	void print_container(const Container& con)
	{
		typename Container::const_iterator it = con.begin();
		while (it != con.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
	}


 

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值