0

I would like to have, in a base class A, a reference (or pointer if not possible) to a pointer in a derived class. This would look like this :

 BaseClassController
        {
          public :
            //Constructors, destructor,...

          protected :
            BaseDataClass *& m_current;
        }

DerivedClassAController : public BaseClassController
    {
      public :
        //Constructors, destructor,...

      protected :
        DerivedDataClassA * m_currentA;
    }

DerivedClassBController : public BaseClassController
    {
      public :
        //Constructors, destructor,...

      protected :
        DerivedDataClassB * m_currentB;
    }

with the Data classes being :

BaseDataClass
{
    void doSomething();
}

DerivedDataClassA : public BaseDataClass
{
 //...
}

DerivedDataClassB : public BaseDataClass
{
 //...
}

What I would like to do next in BaseClassController is :

BaseClassController::someFunction(){
    m_current->doSomething();
}

The problem is that the objects pointed by m_currentA and m_currentB will change a lot through the life of the program, and I would like the m_current reference to change automatically when the derived class pointer changes. Concretly, I would like the function changing the object pointed by m_currentA to look like this :

DerivedClassAController::changerCurrentA(DerivedDataClassA* ptA){
   m_currentA = ptA;
}

and not like this :

DerivedClassAController::changerCurrentA(DerivedDataClassA* ptA){
   m_currentA = ptA;
   m_current = ptA;
}

I tried by passing the pointer in the derived class constructor :

BaseClassController::BaseClassController(BaseDataClass* pt)
 : m_current(pt)
{
}

DerivedClassAController::DerivedClassAController()
 : BaseClassController(m_currentA),
   m_current(A)
{
}

But I ended up having a m_current pointing to a DerivedDataClassB in DerivedClassAController.

Is this acheivable ? Or is there a better way to do that ?

Note : DerivedClassAController will use m_currentA as a DerivedDataClassA 95% of the time. Using only the m_current pointer in the base class will end putting dynamic_cast(m_current) everywhere.

ElevenJune
  • 423
  • 1
  • 4
  • 21
  • `polymorphism` - have you tried it? Can you do everything you need through the `m_current` pointer? – LogicStuff Jul 26 '16 at 13:19
  • 4
    `virtual BaseDataClass* GetCurrent() = 0;` in `BaseClassController`, and have the two derived controllers implement it and return the current value of `m_currentA` or `m_currentB`, respectively. – Igor Tandetnik Jul 26 '16 at 13:20
  • LogicStuff - I added a note to explain why I Can't do it like you suggest. Igor - That could work yes ! I Will try. But I would also like to know if it could work the way I tried – ElevenJune Jul 26 '16 at 13:23
  • As written in your example, `BaseClassController` constructor binds the reference to the local variable `pt` (a copy of `m_currentA`). The reference becomes dangling as soon as the constructor returns. – Igor Tandetnik Jul 26 '16 at 13:23
  • I did not think of that... How should I pass it ? – ElevenJune Jul 26 '16 at 13:26
  • No, you cannot make `m_current` magically change together with `m_currentA`. `BaseDataClass` is not necessarily located at offset zero inside `DerivedDataClassA` - in other words, `m_currentA` may not represent the same memory address as `(BaseDataClass*)m_currentA`. And you cannot produce two distinct addresses with a single assignment. – Igor Tandetnik Jul 26 '16 at 13:27
  • Okay, I understand. Thanks a lot for your answers ! :) I will try your getCurrent implementation – ElevenJune Jul 26 '16 at 13:33
  • As a blanket recommendation: *"don't mess around with 'pointers to things.'"* When you do this, you make a situation that is very fragile and hard to maintain, even if "it seems to work." Instead of letting one class "know how another class works," accessing protected data from it, I suggest that "each class should be responsible for itself." Provide *methods* and *properties,* overriding them as need be, and generally don't pass-around "pointers." Let **all** the code that might affect an object's internal state be ***inside*** that class-definition (or its parent). – Mike Robinson Jul 26 '16 at 13:38
  • Thank for your suggestion Mike, I will take it into account for later ! – ElevenJune Jul 26 '16 at 13:53
  • Have you tried using virtual functions and put the behaviour you require for `DerivedA` instances into the `DerivedA` class, and the `DerivedB` behaviour in `DerivedB`? Therefore no need to do dynamic_cast in the base class because the correct derived function gets called – Steve Lorimer Jul 26 '16 at 14:00
  • No I didn't. In the program DerivedA and DerivedB are extremely different and there base class is just there to factorize the identical behaviour they have. Your suggestion is possible but I do not think it is suitable for my use. I could have given more info about DerivedA and DerviedB but I focused on what was the important part for me, but thanks for your answer ! – ElevenJune Jul 26 '16 at 14:07

1 Answers1

1

I think that following approach would work: Instead of using a member reference, create a virtual function in BaseClassController that returns a copy of the pointer:

struct BaseClassController {
    virtual BaseDataClass* m_current() = 0;

And implement it differently in each derived controller:

BaseDataClass* DerivedDataClassA::m_current() {
    return m_currentA;
eerorika
  • 232,697
  • 12
  • 197
  • 326
  • ... and, I suggest, whenever possible, put the code that would need to *use* that pointer, **inside** the object itself, or its parent(s), so that it isn't necessary to return a pointer at all. That way, "I don't have to go running all over the source-code of the application" to discover all the ways that a particular thing is being manipulated. It's all right here." And if (or rather, *when)* something needs to be changed, it only needs to be changed "once, right here." – Mike Robinson Jul 26 '16 at 13:43
  • It is what I do when possible. The application developped is a CAD using a lot of the MVC Design Pattern. The Controller manipulates the Data Class through a pointer but the rest of the program calls the functions of the Controller. The pointer is not going anywhere away from the controller class and its base class. – ElevenJune Jul 26 '16 at 13:58