为什么没有显式范围解析就无法访问父 类' 的父方法?

Why a method of parent of parent classes' not accessible without of explicit scope resolution?

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

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 class 中看不到内联非虚方法 exec

Why the inline non-virtual method exec is not seen in the device_uart class?

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

根据unqualified name lookup的规则:

name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined.

这意味着名称 exec 将在 device_uart 的范围内找到,然后名称查找停止,基础 class 中的名称将不会被考虑用于重载解析完全没有。

要解决此问题,您可以使用范围解析运算符 :: 使其成为 qualified name lookup,如您所示;要么 您可以使用 using 将名称引入同一范围,重载决议将按预期生效。例如

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