简体   繁体   中英

C++ protected heritage

I have an abstract class AUnit with variables and getters/setters in virtual pure like this

class AUnit {int var... int getVar() const = 0 ... }

All the data is in protected: except constructor and destructor.

I have Berserk and Tank as child like this

class Berserk : public AUnit
{
...
private:
int getVar() const;

In their .cpp, I write the code of the getters and setters. Nothing special.

But I have one other class (foo for example) like this

class Foo : public Berserk, public Tank

who need to access the data in Berserk or Tank so I changed the private keyword by protected, here is the error :

Tank.hpp:36:25: erreur: ‘virtual int Tank::getY() const’ is protected
error inside the context

As first, I just tried to access the data with the AUnit getter but cause of virtual pure and abstract concepts, I thought to reinterpret_cast my AUnit in his real type after passing getType of AUnit in non-pure and in public. Still not working, its the scheme I told you earlier.

It's just classical heritage, can I have some help ?

Your code snipped is certainly incomplete. My guess is that you have something like this:

int Foo::f(Tank const* tank) {
    return tank->getY();
}

(probably, you are doing something more interesting with value than returning it).

Even though access to Tank::getY() is protected , the class Foo won't have access to getY() in the above code because the object pointed to by tank is not known to be a Foo object: a class has only access to protected members in a base object of its own type! That is, the following would be OK:

int Foo::f(Foo const* foo) {
    return foo->getY();
}

So far the only good use I have found for protected a virtual member functions which have a reasonable an non-trivial implementation in a base class and which are called from a [further] derived class as part of overriding the member. This way, functionality can be added and the common logic can be used (of course, any virtual function is not public but rather private or protected ).

It is generally a bad idea to give the overriding function a stricter access protection than the function it overrides. Consider:

class Base {
public:
  virtual void f() {}
};

class Derived : public Base {
private:
  virtual void f() {}  // overrides Base::f
};

Derived d;
d.f();  // error - f is private
Base* pb = &d;
pb->f();  // OK - calls d.f()

To avoid such paradoxes, it is prudent to put overrides at the same access level as the original (or the more relaxed access level, though that's somewhat unusual).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM