2

让我们考虑这段代码:

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.
}

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

4

1 回答 1

3

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

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

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

名称查找检查如下所述的范围,直到找到至少一个任何类型的声明,此时查找停止并且不再检查范围。

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

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

class device_uart : public device
{
  // ...
  using device_base::exec; // introduce the names from base class into the same scope
public:
  // ...
};
于 2017-01-21T06:20:10.540 回答