Note that there are some explanatory texts on larger screens.

plurals
  1. POAccessing a protected member of a superclass-typed member object - an elegant solution
    primarykey
    data
    text
    <p>First off, I know I can not do it, and I think it's not a duplicate questions (<a href="https://stackoverflow.com/questions/477829/cannot-call-base-class-protected-functions">this</a> and <a href="https://stackoverflow.com/questions/7476117/cannot-access-protected-member">this</a> questions deal with the same problem, but they only want an explanation of why it does not work).</p> <p>So, I have a similar concept of classes and inheritance and I would, somehow, elegantly, want to do something that's forbidden. Here's a very simple code snippet that reflects what I <em>want</em> to do:</p> <pre><code>#include &lt;iostream&gt; class A{ protected: int var; std::vector &lt;double&gt; heavyVar; public: A() {var=1;} virtual ~A() {} virtual void func() { std::cout &lt;&lt; "Default behavior" &lt;&lt; this-&gt;var &lt;&lt; std::endl; } // somewhere along the way, heavyVar is filled with a lot of stuff }; class B: public A{ protected: A* myA; public: B(A &amp;a) : A() { this-&gt;myA = &amp;a; this-&gt;var = this-&gt;myA-&gt;var; // copy some simple data, e.g. flags // but don't copy a heavy vector variable } virtual ~B() {} virtual void func() { this-&gt;myA-&gt;func(); std::cout &lt;&lt; "This class is a decorator interface only" &lt;&lt; std::endl; } }; class C: public B{ private: int lotsOfCalc(const std::vector &lt;double&gt; &amp;hv){ // do some calculations with the vector contents } public: C(A &amp;a) : B(a) { // the actual decorator } virtual ~C() {} virtual void func() { B::func(); // base functionality int heavyCalc = lotsOfCalc(this-&gt;myA-&gt;heavyVar); // illegal // here, I actually access a heavy object (not int), and thus // would not like to copy it std::cout &lt;&lt; "Expanded functionality " &lt;&lt; heavyCalc &lt;&lt; std::endl; } }; int main(void){ A a; B b(a); C c(a); a.func(); b.func(); c.func(); return 0; } </code></pre> <p>The reason for doing this is that I'm actually trying to implement a <a href="http://en.wikipedia.org/wiki/Decorator_pattern" rel="nofollow noreferrer">Decorator Pattern</a> (<code>class B</code> has the <code>myA</code> inner variable that I want to decorate), but I would also like to use some of the protected members of <code>class A</code> while doing the "decorated" calculations (in <code>class B</code> and all of it's subclasses). Hence, this example is <em>not a proper example of a decorator</em> (not even a simple one). In the example, <strong>I only focused on demonstrating the problematic functionality</strong> (what I want to use but I can't). Not even all the classes/interfaces needed to implement a Decorator pattern are used in this example (I don't have an <em>abstract base class interface</em>, inherited by <em>concrete base class instances</em> as well as an <em>abstract decorator intreface</em>, to be used as a superclass for <em>concrete decorators</em>). I only mention Decorators for the context (the reason I want a <code>A*</code> pointer).</p> <p>In this particular case, I don't see much sense in making (my equivalent of) <code>int var</code> public (or even, writing a publicly accessible getter) for two reasons:</p> <ul> <li>the more obvious one, I <em>do not</em> want the users to actually use the information directly (I have some functions that return the information relevant to and/or written in my <code>protected</code> variables, but not the variable value itself)</li> <li>the <code>protected</code> variable in my case is much more heavy to copy than an <code>int</code> (it's a 2D <code>std::vector</code> of <code>double</code>s), and copying it in to the instance of a derived class would be unnecessarily time- and memory-consuming</li> </ul> <p>Right now, I have two different ways of making my code do what I want it to do, but I don't like neither of them, and I'm searching for a <code>C++</code> concept that was actually intended for doing something of this sort (I can't be the first person to desire this behavior).</p> <p>What I have so far and why I don't like it:</p> <p><strong>1. declaring all the (relevant) inherited classes <code>friend</code>s to the base class:</strong></p> <pre><code>class A{ .... friend class B; friend class C; }; </code></pre> <p>I don't like this solution because it would force me to <em>modify my base class</em> every time I write a <em>new subclass class</em>, and this is exactly what I'm trying to avoid. (I want to use only the 'A' interface in the main modules of the system.)</p> <p><strong>2. casting the <code>A*</code> pointer into a pointer of the inherited class and working with that</strong></p> <pre><code>void B::func(){ B *uglyHack = static_cast&lt;B*&gt;(myA); std::cout &lt;&lt; uglyHack-&gt;var + 1 &lt;&lt; std::endl; } </code></pre> <p>The variable name is pretty suggestive towards my feelings of using this approach, but this is the one I am using right now. Since I designed this classes, I know how to be careful and to use only the stuff that is actually implemented in <code>class A</code> while treating it as a <code>class B</code>. But, if somebody else continues the work on my project, he might not be so familiar with the code. Also, casting a variable pointer in to something that I am very well aware that it <em>is not</em> just feels pure evil to me.</p> <p>I am trying to keep this projects' code as nice and cleanly designed as possible, so if anybody has any suggestions towards a solution that does not require the modification of a base class every now and then or usage of evil concepts, I would very much appreciate it.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. COI believe that in the decorator pattern, the decorator and the actual objects *implement* an *interface*, that is, the decorator does not *extend* the actual object being implemented, only offers the same interface, and the decoration is applied only to the public interface.
      singulars
    2. CO@DavidRodríguez-dribeas think I edited the explanation in just as you were typing the comment :) What you say is true, but in my actual case, the very top interface contains some data common to *every* concrete instance of the class. So, theoretically, I don't want to access any objects belonging to any of the concrete implementations, just some objects common to every instance of the class that are thus implemented in the interface. But as I just edited in the Q, the example code does not focus on implementing an example Decorator, just an example of my problem situation.
      singulars
    3. COI am having a hard time understanding what it is you are trying to do. I understand you wanted to give a simple example, but right now I don't know which of the weird things in the code are important and which are not. For example, in the constructor for B you copy the var member, but then in class C you use the myA->var directly. Why was the copy necessary, and couldn't you use the copy for your calculation? Let's start there and maybe it will become clearer.
      singulars
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload