I have a class that looks something like this:
class ClassA
{
public:
float Get(int num) const;
protected:
float& Get(int num);
}
Outside of the class, I call the Get() function.
float foo = classAInstance.Get(i);
I expect this to call the public version, but instead Visual Studio errors out:
error C2248: 'ClassA::Get' : cannot access protected member declared in class 'ClassA'
When commenting out the protected overload and removing all references to it, the code compiles.
Why does the compiler try to use the inaccessible member when an accessible one is available? Is there an accepted way to force the compiler to choose the correct overload? Is there a reference to the resolution rules for member functions somewhere?
Overload resolution is done first, and access check later.
If you have both a const and a non-const overload, this is resolved by the constness of the object the function is called for.
It's true, overload resolution takes place before accessibility checks. Section 13.3 of the standard (
[over.match]
) says:The usual fix is to give the public and protected functions different names.
Note, this is useful sometimes, example:
Note that
name_ref
will only be read from, so it's appropriate to make itconst
. However,const
references can bind to temporaries, and bindingname_ref
to a temporary would be a dangling reference, resulting in undefined behavior indo_something_with_name_ref()
.The private constructor overload prevents a temporary
std::string
from being implicitly constructed and bound.