在玩多态性和模板时,我最终挖出了一个奇怪的(至少对我来说)范围运算符的行为。当我尝试使用* i * nterface访问* b * aseclass的方法时,使用* d *中的范围运算符* erived class,我得到一个链接器错误。我只能假设作用域操作符不会查看vtable并尝试直接从接口运行该方法,该接口实际上是纯虚拟的。
这是一个例子:
struct i
{
virtual void set(char* in, short len) = 0;
virtual char* getStr() = 0;
virtual ~i() {}
};
template <int size = 10>
struct b : public i // this one is like an char-Array
{
char str[size];
void set(char* in, short len) { memcpy(this->getStr(),in,len); }
char* getStr() { return str;}
};
template <int size = 10>
struct d : public b<size> // this one is like an cString
{
void set(char* in) { strcpy(this->getStr(),in); }
};
struct final : public d<4>
{
void test()
{
set("abc"); ///< Works
d<4>::set("abc"); ///< Works
//set("abc",3); ///< Error : no matching function for call to 'final::set(const char [4], int)' (its shadowed by d)
//note: candidates are: void d<size>::set(char*) [with int size = 4]
b<4>::set("abc",3); ///< Works
//i::set("abc",3); ///< Linker Error: (.gnu.linkonce.t._ZN5final4testEv+0x68) : Error : undefined reference to `i::set(char*, short)'
//this->set("abc",3); ///< Error : no matching function for call to 'final::set(const char [4], int)' (its shadowed by d too)
((i*) this)->set("abc",3); ///< Works!
}
};
int main()
{
final f;
f.test();
return 0;
}
我尝试这个的背景是,当我可能改变最终类的大小时,避免更改每次调用模板化基类的模板参数。
那么有人可以解释为什么这会在范围运算符中发生吗?
有趣的是,当将“this”指针转换为接口指针然后使用baseclass的方法时,它确实有效。这实际上是否有效且可行?
BTW:我使用的是GCC 4.1.2
编辑: 只是为了澄清,我知道d :: set是影子b :: set ..这不是问题,我只是询问链接器错误!
答案 0 :(得分:0)
在类上下文中编写Base::symbol
时,symbol
会
始终以静态方式解析,名称查找从
班Base
。原因很简单:这就是你访问的方式
派生类中的蒙面成员。否则,你将无法做到
链函数,例如:
void
Derived::function()
{
Base::function(); // calls the function in Base before doing anything else.
// ...
}
在开发C ++时,我们感觉到了这一点 重要的,即使在今天,你也想要支持某种方式 这样做。
解决这个问题的一个想法是:
template <int size=10>
struct d : public b<size>
{
typedef b<size> Base;
// ...
};
然后在final
中,请参阅Base::set
。
答案 1 :(得分:0)