0

Hi I need some clarification on some code since google did not help nor did any of my C++ books. Ok I have a base class,which I derived 2 other classes, but I did not post the code for them here since they don't have anything to do with my question:

ifndef BASEBALLPLAYER_H
#define BASEBALLPLAYER_H

#include <iostream>

using namespace std;

class BaseBallPlayer{                                           //abstract class meaning no instance can be made for it, which is why we access it via derived classes

                                                                //data members
protected:
    string name;
    int height;
    int weight;


public:

    BaseBallPlayer();
    BaseBallPlayer(string nam, int wight, int hight);
    string get_Name();
    virtual void print_player()=0;                                      // 
    virtual void load_player(ifstream & read) = 0;                      // 

    virtual ~BaseBallPlayer();                                          
};

Then an ArrayList.h file:

#ifndef ARRAY_LIST_H
#define ARRAY_LIST_H
#include <string>

using namespace std;
const static int MAX_INIT = 99;

    template <class elemType>
    class ArrayList {
    private:
        int n_element;
        elemType * data;

    public:
        ~ArrayList();
        ArrayList(int n = MAX_INIT);
        ArrayList(const ArrayList<elemType> &);
        const ArrayList<elemType> & operator=(const ArrayList<elemType> &);
        void MakeEmpty();
        bool IsFull() const;
        int  LengthIs() const;
        void RetrieveItem(elemType &, bool&);
        void InsertItem(elemType);
        void DeleteItem(elemType);
        void ResetList();
        bool IsLastItem();
        void GetNextItem(elemType &);
    };

Now my question lies in this new class, its a standalone class, that I made in the PlayerDatabase.h file:

#ifndef PLAYERDATABASE_H
#define PLAYERDATABASE_H

#include <iostream>
#include "BaseBallPlayer.h"
#include "ArrayList.h"

using namespace std;

    class PlayerDatabase{

    private:
        ArrayList<BaseBallPlayer *> teamArrayList; // I do NOT Understand what this means?

    public:

    };
    #endif

I DO NOT understand what the private member in my PlayerDatabse.h file means or entails? And what can I do with it? My instructor told us to usethat template with a pointer but I didn't have a chance to ask what it does/mean?

Deathkamp
  • 45
  • 1
  • 6

2 Answers2

3

So I'm not exactly sure what you end goal is here, but let me take a quick guess at what you might be trying to do:

So you mentioned you have 2 subclasses of BaseBallPlayer, let's say they are MajorLeaguePlayer and MinorLeagePlayer This private Array list teamArrayList can be used to hold any combinations of your base class (BaseBallPlayer -- in your case MajorLeaguePlayer and MinorLeaguePlayer).

You usually want to leave this teamArrayList private so that it will only be safely modified by your public methods. So for example you might want to have a constructor for PlayerDatabase that takes an argument of ArrayList<BaseBallPlayer *>

PlayerDatabase(ArrayList<BaseBallPlayer *> players) {
  // set the private teamArray list in the constructor
  teamArrayList = players;
}

or you might want to sort the teamArray list based off of one of the properties in the base class BaseBallPlayer

// or another one sorting for weight or name
void sortPlayerListByHeight() {
  // sort the private team array list
  teamArrayList = ... // sort by height
}

Maybe you want to get the number of players in the list, or find the first or last player in the list. In general it's good practice to use public methods to access/modify private data members (i.e. teamArrayList)

int numberOfPlayersInList() {
  return teamArrayList.LengthIs();
}

BaseBallPlayer getFirstPlayerInList() {
  return teamArrayList.RetrieveItem.... // get the first item in the list
}

Then from another class you could construct some of your subclass objects and construct your player database:

ArrayList<BaseBallPlayer *> playerList = new ArrayList<>();
playerList.add(new MinorLeagePlayer("minorName", 180,70);
playerList.add(new MajorLeaguePlayer("majorName", 200, 72);
PlayerDatabase db = new PlayerDatabase(playerList);

// now you can do some operations on the PlayerDatabase knowing that the list will contain all objects that can use methods from the Base Class (`BaseBallPlayer`)

db.getFirstPlayerInList().print_player(); // method from your base class implemented in your subclasses


int numberOfPlayers = db.numberOfPlayersInList();
// do something with the number of players in the list

This is pseudo code, but hopefully it will help you get the idea.

Edit related to our comments:

ArrayList<BaseBallPlayer *> *playerList = new ArrayList<BaseBallPlayer *>();
MinorLeaguePlayer *aPlayer = new MinorLeaguePlayer();
playerList->InsertItem(aPlayer);

I've included a couple of simple cout statements in the ArrayList constructor, the MinorLeaguePlayer constructor, and the InsertItem method to output some information when they are called (I'm assuming you already have implementations of these methods):

ArrayList constructor: n_element = n; cout << "Constructing the arrayList, n_element = " << n_element << endl;

MinorLeaguePlayer constructor: cout << "Constructing a minor league player" << endl;

InsertItem method: cout << "Inserting an item into the ArrayList" << endl;

Here's the output after building and running the above code:

Constructing the arrayList, n_element = 99
Constructing a minor league player
Inserting an item into the ArrayList

Edit 2 related to further comments:

Methods which take a reference to the elemType

Example:

// this will basically just going to "hold" the BaseBallPlayer fetched
// from GetNextItem
BaseBallPlayer *bPlayer; 
playerList->GetNextItem(bPlayer);
cout << "Weight after fetching from list = " << bPlayer->weight << endl;

The implementation of GetNextItem is going to look something like this:

void ArrayList<elemType>::GetNextItem(elemType& player) {
// implementation to get the next item in the array list
player = //... set the "NextItem" to the BaseBallPlayer reference we passed into this method
}

Edit 3: print_player() polymorphism:

MinorLeaguePlayer *minPlayer = new MinorLeaguePlayer();
MinorLeaguePlayer *min2Player = new MinorLeaguePlayer();
MajorLeaguePlayer *majPlayer = new MajorLeaguePlayer();
MajorLeaguePlayer *maj2Player = new MajorLeaguePlayer();
playerList->InsertItem(minPlayer);
playerList->InsertItem(min2Player);
playerList->InsertItem(majPlayer);
playerList->InsertItem(maj2Player);

BaseBallPlayer *fetchedPlayer;
for (int i = 0; i < 4; i++) {
    playerList->GetNextItem(fetchedPlayer);
    fetchedPlayer->print_player();

}

Notice that you have to get the reference to the fetchedPlayer prior to calling the print_player() method on it

playerList->GetNextItem(fetchedPlayer);
fetchedPlayer->print_player();

This is because of the way your GetNextItem method is structured to place the reference to the nextItem in the passed in BaseBallPlayer.

Here's another example where the method would return the BaseBallPlayer instead of setting it by reference:

method stub (in ArrayList):
elemType getNextItemReturn();

for loop:
for (int i = 0; i < 4; i++) {
    playerList->getNextItemReturn()->print_player();
}

Here's a link to a quick discussion asking which is more efficient: Which is more efficient: Return a value vs. Pass by reference?

And the output with the example cout statements:

Constructing the arrayList, n_element = 99
Inserting an item into the ArrayList
Inserting an item into the ArrayList
Inserting an item into the ArrayList
Inserting an item into the ArrayList
Printing From MINOR League Player
Player Name: MinorLeagueName Weight = 22
Printing From MINOR League Player
Player Name: MinorLeagueName Weight = 22
Printing From MAJOR League Player
Player Name: MajorLeaguePlayer Weight = 33
Printing From MAJOR League Player
Player Name: MajorLeaguePlayer Weight = 33

The mock implementations of print_player():

void MinorLeaguePlayer::print_player() {
    cout << "Printing From MINOR League Player" << endl;
    cout << "Player Name: " << name << " Weight = " << weight << endl;
}

void MajorLeaguePlayer::print_player() {
    cout << "Printing From MAJOR League Player" << endl;
    cout << "Player Name: " << name << " Weight = " << weight << endl;
}
Community
  • 1
  • 1
R4N
  • 2,455
  • 1
  • 7
  • 9
  • Thank You very much and yes it gives me an idea. I just have one last question tho. Obviously the assignment operator must be overloaded, however what does it mean when some says this operator should also preform self assignment check? – Deathkamp Apr 15 '17 at 00:22
  • @Deathkamp maybe this will be helpful: http://stackoverflow.com/questions/10076285/assignment-operator-overloading-in-c – R4N Apr 15 '17 at 00:30
  • Hey R4N when I do ArrayList playerList = new ArrayList<>(); I get an error under ArrayList<>() that says expected a type identifier? – Deathkamp Apr 15 '17 at 17:15
  • @Deathkamp I believe the error is referring to the ArrayList constructor rather than the BaseBallPlayer constructor. In your ArrayList file you have these constructors: `ArrayList(int n = MAX_INIT); ArrayList(const ArrayList &);` you could try specifying the type in the constructor like `ArrayList playerList = new ArrayList();` – R4N Apr 15 '17 at 17:30
  • I did an new is underlined saying no constructor exist to convert, so should I change my ArrayList.h file constructor from ArrayList(const ArrayList &); to ArrayList(const ArrayList); ? – Deathkamp Apr 15 '17 at 17:36
  • You could also see if this works when creating your ArrayList: `ArrayList playerList = new ArrayList();` Sorry i'm not at a development machine right now so I can't test it out. – R4N Apr 15 '17 at 17:39
  • @Deathkamp I've edited my response to include some more example code. Let me know if allows you to build without encountering the errors anymore. – R4N Apr 15 '17 at 23:16
  • Ah it help alot, its just if I have something like teamArrayList.GetNextItem() since GetNextItem takes a para of (elemType &) what would I put as the parameter? Cause I cant just put playerList I get errors that say error on reference? – Deathkamp Apr 16 '17 at 01:52
  • @Deathkamp here's a quick example: `// this will basically just going to "hold" the BaseBallPlayer fetched // from GetNextItem BaseBallPlayer *bPlayer; playerList->GetNextItem(bPlayer); cout << "Weight after fetching from list = " << bPlayer->weight << endl;` You're passing the bPlayer in by reference so you after you make the method call, bPlayer should contain the "NextItem", this link is probably useful http://www.learncpp.com/cpp-tutorial/73-passing-arguments-by-reference/ – R4N Apr 16 '17 at 06:40
  • I've added a second edit to the example above to display this better. – R4N Apr 16 '17 at 06:47
  • Hey R4N when you said BaseBallPlayer *bPlayer; playerList->GetNextItem(bPlayer); Is there a way to do playerList->GetNextItem(bPlayer.print_player()) ? Basically call a function from either my base class or derived, using a BaseBallPlayer pointer in the GetNextItem parameter? – Deathkamp Apr 18 '17 at 22:26
  • @Deathkamp Yes, that's one of the main points of sub-classing and polymorphism. I've edited the answer again to include an example. – R4N Apr 19 '17 at 05:52
1

teamArrayList is a list of pointers to BaseBallPlayer objects. By using pointers, it can by polymorphic -- the pointers can point to any class derived from BaseBallPlayer.

This is the common way to use an abstract base class. You can then use it to call the methods in the BaseBallPlayer class, and the implementations in the appropriate derived classes will be used.

Barmar
  • 741,623
  • 53
  • 500
  • 612