0

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 ?

Mike
  • 23,542
  • 14
  • 76
  • 87
Khelben
  • 23
  • 1
  • 4
  • In ``class Foo : public Berserk, public Tank`` I guess you mean private, right ? – hivert Jul 26 '13 at 23:05
  • Can you please 'explain' a little more ? I'm not sure to understand your 'question' and your vision of the problem. – Khelben Jul 26 '13 at 23:09
  • Sounds like a [diamond of death](http://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem) to me. – reima Jul 26 '13 at 23:25
  • 1
    @user2624468: You said you replaced private by protected and I only see public... – hivert Jul 26 '13 at 23:35

2 Answers2

1

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

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • I'm searching corrections thanks to your answer but I have one stupid question to ask. If I have an Animal who can be a Cat so Cat : public Animal. I can't use Animal as a Cat cause its not all time the case but I can manipulate Cat as an Animal always so here Foo is a children of Tank so why cant I use the getters of Tank to manipulate my Foo if they are in protected ? For my use, I don't need the real type, abstract is ok. – Khelben Jul 26 '13 at 23:26
  • You can do this with the type of *your* type, i.e., `Foo` in this case. But you can't do this with objects whose type isn't statically known to be a `Foo` but which are only known to be of type `Tank`. That is, `protected` access is only granted to members of a derived type for access to objects of that said derived type. – Dietmar Kühl Jul 26 '13 at 23:32
  • Sorry but can I use your email to send you my 3 classes to have a concrete idea about how to process to succeed this part ? It's hard to explain using foo etc.. – Khelben Jul 26 '13 at 23:37
  • The approach seems to edit the question to clarify it based on comments and answers. I wouldn't make a commitment to review a mail and respond to it! If you edit your question, others can step in and answer it as well. – Dietmar Kühl Jul 26 '13 at 23:39
0

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

Igor Tandetnik
  • 50,461
  • 4
  • 56
  • 85