0

How do I access a derived class's local variable with a base/inherited class's member function?

I'm coming from a JavaScript perspective and while I have some Java experience, it's been a while. Here's the desired outcome in JavaScript.

// JavaScript Example

class State {
    constructor(name){
        this.name = name || "Parent";
    }

    getName(){ return this.name };
}

class StateReading extends State {
    constructor(){
        super("Child");
    }

    // Since StateReading extends State, it also inherits its parent's functions
    // in this case, it inherits getName()

}

const s = new StateReading();
console.log(s.getName());   // I print out "Child"

I'm trying to pull off something similar with C++ but am having a heckuva time getting all the bits (har har) to line up.

#include <iostream>
using namespace std;


 class State {
    std::string name = "Parent";

    public: 
        virtual std::string getName() {  // "virtual" keywords removes the compile time linkage
            return name;
        }
 };

 class StateReading : public State {
     std::string name = "Child";
 };


int main() {

    StateReading sr = StateReading();
    State* s = &sr;  // Make state a pointer to a memory address so it can be reused

    cout<<s -> getName(); // Prints "Parent" ... but I'm pointing to StateReading's memory address ... :/
    cout<<sr.getName(); // At least this one should be child ... wait, it's "Parent" too?!
    return 0;
}

The only way I can get this to work is to override getName() in the child class. But I really don't want to have to override every single method in a child class. I'm trying to work with the concept of polymorphism with a factory pattern. I know I'm always going to be creating a "State" of some kind, but it could be any of a number of derived classes.

// Untested example
class StateFactory{

  public: 
    static make(params){
        switch(params) {
            case 0: return StateReading();
            case 1: return StatePaused();
            case 2: return StateWriting();
            default: // etc.
        }
    }
}


State state = StateFactory.make(params);
state.getName();  // prints out the state's name.  

Any thoughts on this? It seems having to override every derived class to get at local instance variables would be a real maintenance nightmare.

Will Lovett
  • 1,241
  • 3
  • 18
  • 35
  • In JS you call the constructor of the base class. Do the same in C++ – Thomas Sablik Feb 02 '20 at 21:51
  • You don't have to make functions `virtual` if there's only ever going to be one implementation of the function. Example: https://godbolt.org/z/avdcME - but making it `virtual` wouldn't change the fact that `Child` will get printed in both cases if you implement the constructor properly. – Ted Lyngmo Feb 02 '20 at 21:52

2 Answers2

1

In JS you call the constructor of the base class. Do the same in C++

#include <iostream>
using namespace std;


 class State {
 public:
    State() = default;
    State(const std::string &n) : name(n) {}
    virtual ~State() = default;

    std::string getName() {
        return name;
    }
 private:
    std::string name = "Parent";
 };

 class StateReading : public State {
 public:
     StateReading() : State("Child") {}
 };


int main() {

    StateReading sr = StateReading();
    State* s = &sr;  // Make state a pointer to a memory address so it can be reused

    cout<<s -> getName(); // Prints "Parent" ... but I'm pointing to StateReading's memory address ... :/
    cout<<sr.getName(); // At least this one should be child ... wait, it's "Parent" too?!
    return 0;
}

You don't need a virtual method because you don't override it but you should define a virtual destructor: When to use virtual destructors?

Thomas Sablik
  • 16,127
  • 7
  • 34
  • 62
0

You can make the "name" parameter protected in the base class, then you update its value in the constructor of the derived class.

Or, override the base class constructor to accept a string, then you pass it through the derived class constructor. This way you can make the variable "name" private.

  • Welcome to StackOverflow, add some more description and code if it's required to understand the answer because it will resolve someone else problem ASAP – Nensi Kasundra May 13 '20 at 04:50