C++模板类的继承
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++模板类的继承相关的知识,希望对你有一定的参考价值。
template<class c>
class C;
template<class a,class b>
class A:public C<c<a,b>>
;这段代码中……C<c<a,b>>……是什么意思?模板继承的语法究竟是怎样的啊!!
发个能编译通过的,稍微完整一点的吧
C< c<a,b>> 这个写法很奇怪,一个大写的 C,一个小写的c
很晕啊,需要太多的猜测了
还是发完整程序吧
应该很简单的问题,别搞复杂了
^_^ 参考技术B 类模板可以继承也可以被继承。
1.在一个类模板中,一个非依赖型基类是指:无须知道模板实参就可以完全确定类型的
基类。
例如:
template<typename X>
class Base
public:
int basefield;
typedef int T;
;
class D1:public Base<Base<void> >//实际上不是模板
public:
void f()basefield = 3;
;
template<typename T>
class D2:public Base<double>
public:
void f() basefield = 7; //正常访问继承成员
T strange;//T是Base<double>::T,而不是模板参数
;
注意事项:对于模板中的非依赖类型而言,如果在他的派生类中查找一个非受限名称,
那就会先查找这个非依赖型基类,然后才会查找模板参数列表。
2.非依赖性名称不会在依赖基类中查找
template<typename X>
class Base
public:
int basefield;
typedef int T;
;
template <typename T>
class DD:Base<T>
public:
void f()
basefield = 0;//problem
;
template<>
class Base<bool>
public:
enum basefield = 42 ;//tricky
;
void g(DD<bool>& d)
d.f();//opps
//修改方案一
template <typename T>
class DD1:Base<T>
public:
void f()
this->basefield=0;//查找被延迟了
;
//修改方案二
template <typename T>
class DD2:Base<T>
public:
void f()
Base<T>::basefield=0;//查找被延迟了
;
如果使用修改方案二,如果原来的非受限非依赖型名称是被用于虚函数调用的话,
那么引入依赖性的限定的话,那么这种引入依赖性的限定将会近之虚函数调用,
从而也会改变程序的含义,当遇到第二种情况不适合的情况,可以采用方案一本回答被提问者和网友采纳
使用模板访问 C++ 中超类的受保护成员 [重复]
【中文标题】使用模板访问 C++ 中超类的受保护成员 [重复]【英文标题】:accessing protected members of superclass in C++ with templates [duplicate] 【发布时间】:2010-10-24 20:26:23 【问题描述】:为什么 C++ 编译器不能识别 g()
和 b
是 Superclass
的继承成员,如下代码所示:
template<typename T> struct Superclass
protected:
int b;
void g()
;
template<typename T> struct Subclass : public Superclass<T>
void f()
g(); // compiler error: uncategorized
b = 3; // compiler error: unrecognized
;
如果我简化 Subclass
并仅从 Subclass<int>
继承,那么它会编译。当将 g()
完全限定为 Superclass<T>::g()
和 Superclass<T>::b
时,它也会编译。我正在使用 LLVM GCC 4.2。
注意:如果我在超类中将 g()
和 b
设为 public,它仍然会失败并出现同样的错误。
【问题讨论】:
发生这种情况是因为两阶段名称查找(并非所有编译器都默认使用)。这个问题有4个解决方案:1)使用前缀Superclass<T>::b
和Superclass<T>::g()
,2)使用前缀this->a
和this->g()
,3) 添加语句using Superclass<T>::a
和using Superclass<T>::g
,4) 使用启用许可模式的全局编译器开关。这些解决方案的优缺点在***.com/questions/50321788/… 中进行了描述
【参考方案1】:
这可以通过使用using
将名称拉入当前范围来修改:
template<typename T> struct Subclass : public Superclass<T>
using Superclass<T>::b;
using Superclass<T>::g;
void f()
g();
b = 3;
;
或者通过this
指针访问限定名称:
template<typename T> struct Subclass : public Superclass<T>
void f()
this->g();
this->b = 3;
;
或者,正如您已经注意到的,通过限定全名。
之所以有必要这样做是因为 C++ 没有考虑超类模板来进行名称解析(因为它们是从属名称并且不考虑从属名称)。它在您使用 Superclass<int>
时有效,因为它不是模板(它是模板的实例化),因此它的嵌套名称不是依赖 名称。
【讨论】:
微软的编译器不遵守这个规则。我很生气 @Armen:只有这一条规则?哇,它真的已经变得更好了。 :-Dthis
指针解决方案适用于我在 Mac 10.7 上使用 stock g++。
请注意,如果模板参数过多,您也可以使用Subclass::Superclass::
进行限定。
我有点喜欢微软不遵守这条规则。我真的希望有一个选项可以将模板的所有符号检查延迟到实例化。它将显着提高模板的表现力并减少许多语法噪音。【参考方案2】:
康拉德的回答并没有问或回答所有这一切中的最后一个“为什么”。不仅仅是 C++ 委员会武断地说“嘿,放弃从属名称,反正没人喜欢它们”。相反,编译器甚至在它们被实例化之前就对模板进行了一些检查,并且在它知道 T 之前它无法理解 g() 或 b,因为它不能 - 通常 - 在可能的特化之间进行选择基类(例如SuperClass<X>
可能有int b
而SuperClass<Y>
有void b()
和SuperClass<Z>
根本没有b
)。更明确的形式只是说“相信我 - 这必须在实例化时来自基类(否则会出现编译器错误)”。
【讨论】:
有点道理,但它绝对是模板中比较晦涩的“功能”之一。 @ChrisWue:那场比赛竞争激烈! ;-) GCC 在过去(1990 年代)能够处理这个问题,但后来随着 C++ 的发展,它发生了变化。我认为它的处理方式在某些情况下会导致问题,这就是它被改变的原因。以上是关于C++模板类的继承的主要内容,如果未能解决你的问题,请参考以下文章
学习c++ 第四天 类 及类的继承--class和struct的区别--static成员