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>>……是什么意思?模板继承的语法究竟是怎样的啊!!

参考技术A 这么短的程序,不好分析啊
发个能编译通过的,稍微完整一点的吧

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()bSuperclass 的继承成员,如下代码所示:

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&lt;int&gt; 继承,那么它会编译。当将 g() 完全限定为 Superclass&lt;T&gt;::g()Superclass&lt;T&gt;::b 时,它也会编译。我正在使用 LLVM GCC 4.2。

注意:如果我在超类中将 g()b 设为 public,它仍然会失败并出现同样的错误。

【问题讨论】:

发生这种情况是因为两阶段名称查找(并非所有编译器都默认使用)。这个问题有4个解决方案:1)使用前缀Superclass&lt;T&gt;::bSuperclass&lt;T&gt;::g()2)使用前缀this-&gt;athis-&gt;g()3) 添加语句using Superclass&lt;T&gt;::ausing Superclass&lt;T&gt;::g4) 使用启用许可模式的全局编译器开关。这些解决方案的优缺点在***.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&lt;int&gt; 时有效,因为它不是模板(它是模板的实例化),因此它的嵌套名称不是依赖 名称。

【讨论】:

微软的编译器不遵守这个规则。我很生气 @Armen:只有这一条规则?哇,它真的已经变得更好了。 :-D this 指针解决方案适用于我在 Mac 10.7 上使用 stock g++。 请注意,如果模板参数过多,您也可以使用Subclass::Superclass:: 进行限定。 我有点喜欢微软不遵守这条规则。我真的希望有一个选项可以将模板的所有符号检查延迟到实例化。它将显着提高模板的表现力并减少许多语法噪音。【参考方案2】:

康拉德的回答并没有问或回答所有这一切中的最后一个“为什么”。不仅仅是 C++ 委员会武断地说“嘿,放弃从属名称,反正没人喜欢它们”。相反,编译器甚至在它们被实例化之前就对模板进行了一些检查,并且在它知道 T 之前它无法理解 g() 或 b,因为它不能 - 通常 - 在可能的特化之间进行选择基类(例如SuperClass&lt;X&gt; 可能有int bSuperClass&lt;Y&gt;void b()SuperClass&lt;Z&gt; 根本没有b)。更明确的形式只是说“相信我 - 这必须在实例化时来自基类(否则会出现编译器错误)”。

【讨论】:

有点道理,但它绝对是模板中比较晦涩的“功能”之一。 @ChrisWue:那场比赛竞争激烈! ;-) GCC 在过去(1990 年代)能够处理这个问题,但后来随着 C++ 的发展,它发生了变化。我认为它的处理方式在某些情况下会导致问题,这就是它被改变的原因。

以上是关于C++模板类的继承的主要内容,如果未能解决你的问题,请参考以下文章

学习c++ 第四天 类 及类的继承--class和struct的区别--static成员

C++继承的应用

C++继承:公有,私有,保护

C++多继承

C++中,子类会继承父类的虚函数表!对于父类的析构函数(虚函数) 也会继承吗?

用类的继承关系实现简易后台代码模板