只是示例代码:
template <class T> class TempBase
{
protected:
string m_str;
};
template <class T> class Temp: public TempBase<T>
{
public:
void method()
{
string
&s = TempBase<T>::m_str //reference works fine
/*NOTE compile failed:
error: ‘std::string TempBase<int>::m_str’ is protected
error: within this context
error: cannot convert ‘std::string TempBase<int>::* {aka std::basic_string<char> TempBase<int>::*}’ to ‘std::string* {aka std::basic_string<char>*}’ in initialization
*/
, *ps = &TempBase<T>::m_str
, *ps2 = &m_str //compile failed, obviously: ‘m_str’ was not declared in this scope
, *ps3 = &s //this is workaround, works fine
;
}
};
void f()
{
Temp<int> t;
t.method();
}
目标:使用祖先成员std::string *
初始化TempBase<T>::m_str
类型的指针。
问题:正确的语法未知
评论:以前的代码包含2个故意编译错误:
和1种解决方法。
问题:在这种情况下获取指向祖先数据的指针的正确语法是什么?
答案 0 :(得分:2)
我将假设解决方法最好地描述了您想要的行为
&s = TempBase<T>::m_str;
(您在问题中提供)而非解决方法
&s = this->m_str;
在你的例子中也会起作用。
解决方案:&amp;(TempBase :: m_str)
原因:TempBase :: m_str是一个限定ID,(TempBase :: m_str)不是。
代码示例:
#include <iostream>
#include <string>
using namespace std;
template <class T> class TempBase
{
protected:
string m_str;
};
template <class T> class Temp: public TempBase<T>
{
public:
void method()
{
string* ps3 = &(TempBase<T>::m_str); //this is workaround, works fine
(*ps3) += "ciao";
cout << *ps3 << endl;
}
};
void f()
{
Temp<int> t;
t.method();
}
int main( int argc, char* argv[] )
{
f();
}
您可以尝试here
答案 1 :(得分:1)
&m_str
不起作用的原因:[temp.dep] / 3
在类或类模板的定义中,如果基类依赖于 template-parameter ,则在非限定名称查找期间不会检查基类范围[...]
但是,this->m_str
表示依赖名称(因为this
依赖于[temp.dep.expr] / 2)。在这种情况下,使用依赖名称查找,它查找基类成员。
如果我们添加模板的特化和类范围之外的名称,问题就更明显了:
string m_str;
template<class T> struct A { string m_str; };
template<> struct A<int> { /* no member */ };
template<class T> struct B : A
{
void foo() { m_str = "hello"; }
};
B<int>().foo(); // clearly modifies the global `m_str`
B<double>().foo(); // modifies what?
如果搜索了基类范围,则在实例化之前(在知道模板参数之前)将不知道m_str
引用的内容。此外,这很容易导致意想不到的结果。
因此,不搜索基类范围(如果基类是依赖的,如果我们在“模板上下文中”)。
&s = TempBase<T>::m_str
有效的原因:
id-expression TempBase<T>::m_str
正在使用 qualified-id ,因此会搜索TempBase<T>
的范围并且成员{{1找到了。
m_str
不起作用的原因,&TempBase<T>::m_str
的确如此:[expr.unary.op] / 3
一元
&(TempBase<T>::m_str)
运算符的结果是指向其操作数的指针。操作数应为左值或 qualified-id 。如果操作数是 qualified-id ,则命名类型为&
的某个类m
的非静态成员C
,结果的类型为“指向成员的指针属于T
类的C
类,并且是指定T
的prvalue。否则,如果是类型 表达式为C::m
,结果具有类型“指向T
的指针”,并且是一个prvalue,它是指定对象的地址(1.7)或指向指定函数的指针。
paranthesized表达式T
不是 qualified-id ,因此(TempBase<T>::m_str)
不会形成指向成员的指针,而是指向对象的普通指针&(TempBase<T>::m_str)
。