Because A
is making the call to otherA.hello();
. You cannot call into it private
or protected
code directly, but descendants of A
, including A
itself, can call into A
(descendants cannot access A
's private
data/methods, but A
can access A
's private
data/methods). Relatedly, A
can also access the private
data/methods of other instances of A
(this is generally how copy constructors and assignment operators work).
In fact, it's the ability to use protected
code within the class
that enables the creation of some very powerful OO concepts. With that said, I see it as an abuse to call an inner-object's private
or protected
methods even when possible, but using them directly against yourself is hopefully by design rather than convenience.
In C++, you can provide abstract implementations of class
es (or struct
s for that matter) by marking items as virtual
and not providing an implementation.
class A
{
public:
void set_value(const std::string &value)
{
if (is_valid(value))
{
this->value = value;
}
}
const std::string &get_value() const
{
return value;
}
protected:
virtual boolean is_valid(const std::string &value) const = 0;
private:
std::string value;
}
Then
class B : public A
{
protected:
virtual boolean is_valid(const std::string &value) const
{
return value != "abc";
}
}
Notice that A
is setup to inherit functionality, and it is built to anticipate it being supplied (granted the example above doesn't really provide a lot of utility, but it does show what I mean).