为什么父类的父类方法在没有显式范围解析的情况下无法访问?



让我们考虑一下这个代码:

struct message
{
uint8_t* data;
size_t length;
};
class device_base
{
// ...
public:
virtual ssize_t exec(uint8_t cmd, const uint8_t* data = nullptr, size_t length = 0);
inline ssize_t exec(uint8_t cmd, const message& msg)
{
return exec(cmd, msg.data, msg.length);
}
// ...
};
class device : public device_base
{
// The exec method do not overloaded or overridden here.
};
class device_uart : public device
{
// ...
public:
ssize_t exec(uint8_t cmd, const uint8_t* data = nullptr, size_t length = 0);
void some_method(const message&);
// ...
};
// ...
void device_uart::some_method(const message& msg)
{
// exec(SOME_COMMAND, msg); // The inline method device_base::exec is invisible here by some reason.
device::exec(SOME_COMMAND, msg); // OK.
device_base::exec(SOME_COMMAND, msg); // OK too.
exec(SOME_COMMAND, msg.data, msg.length); // OK, of course.
}

为什么在device_uart类中看不到内联非虚拟方法exec

为什么在device_uart类中看不到内联非虚拟方法exec

这是一种"名称隐藏";在类device_uart的成员函数中,device_base::exec是隐藏的,因为类device_uart本身中有一个同名的方法exec。函数不能通过不同的作用域重载。

根据不合格名称查找规则:

名称查找如下所述检查作用域,直到在至少一个任何类型的声明,此时查找停止,并且没有检查进一步的范围。

这意味着名称exec将在device_uart的作用域中找到,然后名称查找停止,基类中的名称根本不会被考虑用于重载解析。

为了解决这个问题,您可以使用范围解析运算符::使其符合所示的名称查找;或您可以使用using将名称引入同一范围,重载解决方案将按预期生效。例如

class device_uart : public device
{
// ...
using device_base::exec; // introduce the names from base class into the same scope
public:
// ...
};

相关内容

最新更新