C++模板类继承中的Name Lookup

转载 2016年06月03日 00:31:49

转载自http://www.wuzesheng.com/?p=2244
今天这篇文章说说C++中的模板类继承时的名称(变量/类型)查找(Name Lookup)。普通的继承关系中的Name Lookup对于熟悉C++的同学来说,都是非常直观的,因此在这里就不再赘言。模板类(Template Class)的继承中,由于模板本身特殊性,使其在Name Lookup时,有着一定的特殊性,我们从一个例子来说明:

template< typename T>
class A
{
protected:
    int m_data;
};

template< typename T>
class B : public A< T>
{
public:
    void Test(int t)
    {   
        m_data = t;
    }   
};

int main(int argc, char** argv)
{
    B< int> b;
    b.Test();
}

看完上面这个例子,如果有同学能一眼看出这个例子中存在的问题,那后面的内容可以不用看了,这篇文章中要讲的内容你是清楚的。如果看不出,那我们继续来看这个例子会有什么问题。我们用g++(v4.5.1)来编译上面的例子:

zeshengwu@TengDa_10_12_22_98:~/work/test> g++ test.cc -o test
test.cc: In member function 'void B< t>::Test(const T&)':
test.cc:18:9: error: 'm_data' was not declared in this scope

神马?m_data没有声明?明明不是在基类A< T>里已经声明了吗?为什么这里编译器会说没有声明呢?难道是编译器有bug?非也非也,g++/gcc是久经考验的工具,它出bug的概率肯定比我们写的程序出bug的概率要小得多,本着任何时候都要先怀疑自已的精神,我们来找寻这里的问题的答案。
我们知道,在普通的继承关系中,Name Lookup的基本顺序是先从子类里找,如果在子类里找不到,再从基类里找。按照这个理论,m_data应该可以从基类A< T>里找到。且慢,我们来看看C++Std文档中是怎么说的:

The lookup of names dependent on the template parameters is postponed until the actual 
template argument is known

这句话的大意是说“依赖于模板参数的Name Lookup会推迟到模板参数的实际类型确定的时候(也就是模板实例化的时候)”。在上面的程序中,由于m_data依赖于基类A< T>,而基类A< T>又依赖于子类B< T>的模板参数T。因此,在B< T>中定义Test()函数的时候,m_data的lookup会被推迟到A< T>实例化的时候。这时候,就不知道m_data是从哪里来的了。那如何来解决呢?解决的方法就是显式的指明m_data是从哪里来的,具体有下面两种方案:
方案一:

...
void Test(const T& t)    
{   
    A< T>::m_data = t;
}
...

方案二:

...
void Test(const T& t)    
{   
    this->m_data = t;
}
...

C++模板类继承中的Name Lookup

今天这篇文章说说C++中的模板类继承时的名称(变量/类型)查找(Name Lookup)。普通的继承关系中的Name Lookup对于熟悉C++的同学来说,都是非常直观的,因此在这里就不再赘言。模板类...
  • RobertChenGuangzhi
  • RobertChenGuangzhi
  • 2015年07月30日 21:26
  • 583

C++ 模板 two-phase name lookup

// two_phase_name_lookup.cpp #include namespace A { // 3: template void ...
  • luansxx
  • luansxx
  • 2013年11月25日 18:07
  • 900

C++模板类的继承1 :模板类继承模板类

大学时代旧作。       模板类的继承是C++中较为高级的一种用法,其语法与普通C++类的继承略有差别。本文实例演示了一个通过C++模板类继承实现排序算法的案例。代码如下: 1.   实现List基...
  • u011747351
  • u011747351
  • 2013年08月25日 13:53
  • 1218

C++的Name lookup之qualified name lookup

1. 简介C++中Name lookup的过程就是一个通过name找到对应申明的过程。对于函数来说,name lookup可能会匹配出很多个申明,然后如果是函数再通过Argument-dependen...
  • lastsweetop
  • lastsweetop
  • 2015年10月27日 17:50
  • 2245

C++--继承中的类模板语法

当模板遇上继承之后会发生什么呢? 写一个简单的测试案例来说明当模板与上继承发生的“”大事件“” #include using namespace std; template class A {...
  • sum_TW
  • sum_TW
  • 2016年12月08日 17:39
  • 2296

C++模板类的继承2:普通类继承模板类

在上一篇文章中,介绍了C++中模板类继承的实现。本文补充介绍如何从C++模板类中派生出一个普通类,或者说实现一个普通类A,继承至一个模板类B。 1.实现List基类(模板类) #ifndef LI...
  • u011747351
  • u011747351
  • 2013年08月25日 13:57
  • 1267

c++编译错误提示[Error] name lookup of 'i' changed for ISO 'for' scoping

在VC 6 中,i的作用域范围是函数作用域,在for循环外仍能使用变量i 即: for (int i = 0; i < n; ++i) { //…… } cout...
  • sax_157001
  • sax_157001
  • 2016年05月25日 10:50
  • 5717

一般c++编译出现"name lookup of '变量名' changed [enabled by default]"的警告

如果你在局部作用域嵌套了同名局部变量会出现这个错误 : name lookup of '变量名' changed [enabled by default] { int a;   {    in...
  • zszeng
  • zszeng
  • 2014年12月20日 16:10
  • 2522

自学QT之报错: name lookup of 'i' changed for ISO 'for' scoping

这个是因为编译器不识别语法导致的,你需要在程序指出的位置检查是否存在语法问题,有的是语法标准问题,也有的是语法写错了。 比如这里就是漏写了一个int,没有指定i的类型。 #include #in...
  • xuancailinggan
  • xuancailinggan
  • 2015年08月24日 10:38
  • 3201

C++ 的名字查找(name lookup)

C++名字查找有两个方法: 一个是OL(ordinary name lookup) 普通查找规则 一个是ADL(argument-depentment lookup)依赖于实参的名字查找(也称KL法)...
  • fullyanfmotr
  • fullyanfmotr
  • 2016年01月01日 17:58
  • 324
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++模板类继承中的Name Lookup
举报原因:
原因补充:

(最多只允许输入30个字)