Let's consider this code:
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.
}
Why the inline non-virtual method exec
is not seen in the device_uart
class?
Why the inline non-virtual method
exec
is not seen in thedevice_uart
class?
This is a kind of "name-hiding"; in the member function of class device_uart
, device_base::exec
is hidden because there's a method with same name exec
in the class device_uart
itself. Functions can't be overloaded through different scopes.
According to the rule of 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.
That means the name exec
will be found at the scope of device_uart
, then name lookup stops, the names in the base class won't be considered for overload resolution at all.
To solve the issue, you can use scope resolution operator :: to make it qualified name lookup as you've shown; or
you can use using
to introduce the names into the same scope, the overload resolution would take effect as expected. e.g.
class device_uart : public device
{
// ...
using device_base::exec; // introduce the names from base class into the same scope
public:
// ...
};