How to transfer values set in privates of base class by an object of one derived class to an object of another derived class?

StackOverflow https://stackoverflow.com/questions/23312993

Question

I have my main.cpp like this:

#include <iostream>

#include "curve1.h"
#include "curve2.h"

using namespace std;

int main()
{
    Curve1 curve1Obj;
    Curve2 curve2Obj;

    curve1Obj.enterScores();

    curve1Obj.calcAverage();

    curve1Obj.output();

    curve1Obj.curve();

    curve1Obj.output(curve1Obj.new_getAverage1(), curve1Obj.new_getScore1());

    curve2Obj.curve();

    return 0;
}

Base class Score has two derived classes Curve1 and Curve2. There are two curve() functions, one is in Curve1 and other in Curve2 classes. getSize() returns the value of iSize.

My base class header score.h looks like this:

#ifndef SCORE_H
#define SCORE_H

class Score 
{

private:

    int *ipScore;
    float fAverage;
    int iSize;

public:

    Score(

    void enterScores();
        void calcAverage();
        void output();
    void output(float, int*);

    void setSize();
    int getSize();

    void setScore();
    int *getScore();

    float getAverage();
};

#endif 

You can see that I have used curve1Obj to enter scores, calculate average and output. So if I call getSize() function with cuve1Obj, it gives the right size that I took from user in enterScores() function. Also the result is same if I call getSize() in score.cpp definition file in any of the functions (obviously). ..... The problem is when I call curve() function of Curve2 class in main (line 23) with the object curve2Obj, it creates a new set of ipScore, fAverage and iSize (i think?) with garbage values. So when I call getSize() in curve() definition in curve2.cpp, it outputs the garbage. ..... How can I cause it to return the old values that are set in curve1.cpp?

Here is my curve2.cpp

#include <iostream>

#include "curve2.h"

using namespace std;

void Curve2::curve()
{
    cout << "getSize() returns: " << getSize() << endl; // out comes the garbage
}

Can I use a function to simply put values from old to new variables? If yes then how?

Was it helpful?

Solution

Well, basically your problem can't be easily solved the way it is. Like you said:

1 - Don't use constructors of any type. 2 - Don't use vectors. 3 - Using dynamic new and delete etc. etc.

Use the constructors or stick with what G. Samaras and Richard Hodges said. You can only solve this that way.

OTHER TIPS

There is limited information available here but I would say that your Score constructor has not initialised ipScore or iSize.

If you are hell-bent on using a pointer to a dynamically allocated array of ints for your score then at least null out the pointer in the constructor and test for null in the average function (i.e. no scores yet).

Better yet... use a std::vector of int for your scores.

Why are people still using new and delete? What the hell are they teaching in schools?

What I think you want is this:

#include <vector>

class Score {
public:
    Score()
    : _scores()
    , _average(0)
    { }

    void calcAverage() {
        double total = 0;
        if(auto s = _scores.size() > 0) {
            for (const auto& v : _scores)
                total += v;
            total /= s;
        }
        _average = total;
    }

    virtual void curve() = 0;

protected:
    // one of the few correct uses of 'protected' - giving limited access to data as interface to derived classes
    const std::vector<double>& scores() const {
        return _scores;
    }

    // or
    std::vector<double> copyScores() const {
        return _scores;
    }

private:
    // use doubles since you'll be doing floating point arithmetic
    std::vector<double> _scores;    
    double _average;
};

class Curve1 : public Score {
public:
    virtual void curve() override {
        // custom curve function here
        // written in terms of scores() or copyScores() if you want to make changes to the array
    }    
};

class Curve2 : public Score {
public:
    virtual void curve() override {
        // custom curve function here
        // written in terms of scores();
    }    
};

You need to understand inheritance. Curve1 inherits from Score. Curve2 inherits from Score.

Now see this example:

#include <iostream>

class Base {
  int x;
};

class A : public Base {
  int a;
 public:
  void set_a(int arg) {
    a = arg;
  }
  int get_a() {
    return a;
  }
};

class B : public Base {
  int b;
 public:
  void set_b(int arg) {
    b = arg;
  }
  int get_b() {
    return b;
  }
};

int main() {
  A a_object;
  a_object.set_a(4);

  B b_object;
  b_object.set_b(a_object.get_a());

  std::cout << "a of a_object = " << a_object.get_a() << "\n";
  std::cout << "b of b_object = " << b_object.get_b() << "\n";

  return 0;
}

class A, has as members x and a. Class B has as members x and b. When I create an instance of class A, I will two data members created internally, x and a. When I create an instance of class A, I will two data members created internally, x and b. But, the first x and the second are DIFFERENT. They are a different cell in the memory!

something like this:

class Score {
public:
    Score()
    : _scores(0)
    , _size(0)
    , _average(0)
    { }

    // copy constructor
    Score(const Score& rhs)
    : _scores( new double[rhs._size] )
    , _size(rhs._size)
    , _average(rhs._average)
    {
        if (_size) {
            for(int i = 0 ; i < _size ; ++i) {
                _scores[i] = rhs._scores[i];
            }
        }
    }

    // ... and if copy constructor then always a copy operator

    Score& operator=(const Score& rhs) {
        // assignment in terms of copy constructor - don't repeat yourself
        Score tmp(rhs);
        swap(tmp);
        return *this;
    }

    // pre c++11 we make our own swap. 
    // post c++11 we would make non-throwing move constructor and move-assignment operator

    void swap(Score& rhs) {
        // std::swap is guaranteed not to throw
        std::swap(_scores, rhs._scores);
        std::swap(_size, rhs._size);
        std::swap(_average, rhs._average);
    }

    ~Score()
    {
        delete[] _scores;
    }

    void calcAverage() {
        double total = 0;
        if(_size > 0) {
            for (int i = 0 ; i < _size ; ++i)
                total += _scores[i];
            total /= _size;
        }
        _average = total;
    }

    virtual void curve() {};

private:
    // use doubles since you'll be doing floating point arithmetic
    double * _scores;    
    int _size;
    double _average;
};

// rmember to override the copy operators and assignment operators of derived classes
// remember to call the base class's operator
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top