在玩弄多态性和模板时,我最终发现了范围运算符的一个奇怪(至少对我而言)行为。当我尝试使用 * i * 接口和 * d *erived 类中的范围运算符访问 a * b *aseclass 的方法时,我收到链接器错误。我只能假设作用域运算符不查看 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”指针转换为接口指针然后使用基类的方法时,它确实有效。这真的有效和可行吗?
顺便说一句:我使用 GCC 4.1.2
编辑:澄清一下,我知道 d::set 正在遮蔽 b::set .. 这不是问题,我只是在询问链接器错误!