2015-09-04 99 views
2

我们来看看这个简单的代码示例,其中包括基类和从Base派生的类,它需要基类成员在其构造函数中的地址。从C++中的派生类构造函数中的基类模板类访问变量

#include <vector> 
#include <inttypes.h> 
#include <stdio.h> 

class Base 
{ 
protected: 
    std::vector<uint32_t> arr; 
public: 
    Base(std::vector<uint32_t> arr_in): arr(arr_in) {} 
}; 

class Derived: public Base 
{ 
private: 
    uint32_t *parr; 
public: 
    Derived(std::vector<uint32_t> arr_in): Base(arr_in) 
    { 
    parr = &arr[0]; 
    } 

    uint32_t *get_parr(); 
}; 

uint32_t *Derived::get_parr(void) 
{ 
    return parr; 
} 

int main() 
{ 
    std::vector<uint32_t> myarr(3, 1); 
    Derived myderived(myarr); 
    printf("myderived.myarr adress = %p", myderived.get_parr()); 
} 

由于派生类的构造函数调用基类构造第一和仅然后对其执行代码块,基类中的成员可以已经被访问。所以一切正常。

现在我更改代码示例,以便我的两个类都是模板。

#include <vector> 
#include <inttypes.h> 
#include <stdio.h> 

template<typename T> 
class Base 
{ 
protected: 
    std::vector<T> arr; 
public: 
    Base(std::vector<T> arr_in): arr(arr_in) {} 
}; 

template<typename T> 
class Derived: public Base<T> 
{ 
private: 
    T *parr; 
public: 
    Derived(std::vector<T> arr_in): Base<T>(arr_in) 
    { 
    parr = &arr[0]; 
    } 

    T *get_parr(); 
}; 

template<typename T> 
T *Derived<T>::get_parr(void) 
{ 
    return parr; 
} 

int main() 
{ 
    std::vector<uint32_t> myarr(3, 1); 
    Derived<uint32_t> myderived(myarr); 
    printf("myderived.myarr adress = %p", myderived.get_parr()); 
} 

但是这第二个示例给了我以下错误消息时编译:

class_temp.cpp: In constructor ‘Derived<T>::Derived(std::vector<T>)’: 
class_temp.cpp:23:13: error: ‘arr’ was not declared in this scope 
    parr = &arr[0]; 

那么,为什么是它与模板类第二样品中的派生类的构造不知道基地班级成员? 或者我在这里做错了什么?

谢谢。

+1

我确定这是重复的,但由于某种原因我找不到任何东西。 – Barry

回答

6

arr现在是一个依赖名称。这取决于T。如果有一些T为什么Base<T>专门没有arr?具体地,从[temp.dep]:

在一类或类模板的定义中,从属基类的范围(14.6.2.1)也不会被在不合格的名称查找所检验 类模板或成员的定义点或在类模板或成员的实例化过程中。

Base<T>是依赖基类 - 这取决于模板参数T,所以在不合格名称查找未审查的范围。解决方法是使用合格的名称查找。也就是说,无论是类名:

parr = &Base<T>::arr[0]; 

或只是this

parr = &this->arr[0]; 
+0

为什么'parr =&Base :: arr [0];'有效?由于'Derived'继承了'class Derived:public Base ',如果存在专用于'Base '的情况,可能会导致'arr'不存在,但是为什么相同的逻辑不适用于'&Base :: arr [0]'? – Allanqunzi

+0

@Allanqunzi由于在**不合格**查找过程中没有查找依赖基类的范围 - 如果我们执行'Base :: arr',我们正在进行合格的查找。如果'arr'不存在,那将是一个查找失败 - 但是如果它确实存在,我们会发现它。 – Barry

+0

谢谢,你的第一句话是我错过的。 – Allanqunzi

1

在第二种情况下,Base是一个模板,有人可能会为模板添加特,都具有不同的成员变量。直到它看到T是什么,编译器才能知道。

也可能有一个全球arr,可以适合。通过使用this->arr[0]可以帮助编译器指出它始终是一个成员变量。

相关问题