Search code examples
c++inheritanceoperator-overloadingsplicemember-access

Outputting member variables when data is spliced c++


Hello I currently face a problem were I want to output data from 2 separate classes, one is a base class and one is a derived class, I want to overload the << operator to output all the data at once but seem to have trouble doing so, I have something like this:

#include <iostream>
using namespace std;

class A
{
    char* A;
    char* B;

public:
    A() {A = ' '; B = ' ';}
    A(char* pLast, char* pFirst)
    {

        A = new char [strlen(pLast) + 1];
        B = new char [strlen(pFirst) + 1];

        strcpy(A,pLast);
        strcpy(B,pFirst);
    };
}

class C:public A
{
    int X;
    char Y;
    int Z;
public:
    C(char* A, char* B, int X, char Y, int Z)
        :A(A,B)
    {
        //do stuff here
    }
    friend std::ostream& operator<<(std::ostream& out, const C& outPut)
    {
        out << outPut.A << "," << outPut.B << "," <<outPut.X<< "," << outPut.Y << "," << outPut.Z << endl;
        return out;
    }
};

When I try to run this it tells me A and B are out of range which makes sense since those members are private in class A, I don't know how to get around this. I tried creating getter methods to access A and B but the data comes out as blank. I even tried added an object of class A as a member of class B to try to allow access to the members in class B still the data comes out blank. How do I get around this problem?


Solution

  • There are several ways of dealing with this. One way obviously is to make the members of A protected rather than private. A derived class B can then access them.

    Another way indeed are getter functions. The fact they didn't work for you is related to problems in your constructors and other problems in your code. But public getters also have the disadvantage of enabling anyone (not just derived classes) to get access to the values of your data members.

    Here is a third approach, which I believe makes sense in your case: Define a separate operator<< in A, and make use of that operator when you define the one for B:

    #include <cstring>
    #include <iostream>
    
    using namespace std;
    
    class A
    {
      char* _a;
      char* _b;
    public:
      A()
        : _a(),_b()
      { }
    
      A(const char *pLast, const char *pFirst)
        : _a(new char [std::strlen(pLast)]),
          _b(new char [std::strlen(pFirst)])
      {
        strcpy(_a,pLast);
        strcpy(_b,pFirst);
      }
    
      friend std::ostream& operator<<(std::ostream& out, const A& obj) 
      {
        out << obj._a << "," << obj._b;
        return out;
      }
    };
    
    class B : public A
    {
      int  _x;
      char _y;
      int  _z;
    
    public:
      B(const char *pLast, const char *pFirst, int x, char y, int z)
        : A(pLast,pFirst),
          _x(x),_y(y),_z(z)
      { }
    
      friend std::ostream& operator<<(std::ostream& out, const B& obj)
      {
        out << static_cast<const A&>(obj) << ','
            << obj._x << ','
            << obj._y << ','
            << obj._z;
        return out;
      }
    };
    
    int main()
    {
      B b("hello","world",1,'a',3);
      std::cout << b << std::endl;
      return 0;
    }
    

    I've also corrected the other problems I found, so the above actually works.