Connecting Classes Question

Hello folks!

I am attempting the "Graduation" beginner exercise (http://www.cplusplus.com/forum/articles/12974/) and am having trouble visualizing how to connect classes. I'm rather new to programming and would appreciate some insight on how to utilize one class in another.

Specifically, I created a NameList class that reads a list of names from a file and stores them in a dynamically-created array. NameList has a public method getRandomName() to return a name from the list selected at random.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// namelist.h
// NameList reads names from a file and stores them in a list.
#ifndef NAMELIST_H_
#define NAMELIST_H_

#include <fstream>
#include <string>

class NameList
{
private:
	static const std::string fileName;
	std::string * nameList;
	std::ifstream fin;
	int listSize;
public:
	NameList();
	~NameList();
	void printList() const;
	std::string getRandomName() const;	// Return a random name from list
};
#endif 

I also created a Bunny class to represent each bunny. The constructor initializes various attributes (color, sex, etc), and I want the constructor to utilize the getRandomName() to populate the name field.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// bunny.h
// Define Bunny class
#ifndef BUNNY_H_
#define BUNNY_H_

#include <string>
#include <iostream>
#include "namelist.h"

class Bunny
{
private:
	enum Color {white, brown, black, spotted};
	enum Sex {female, male};
	NameList nameList;       // Problem! New list every time bunny obj created.
	std::string name;
	Color color;	
	Sex sex;	
	int age;		
	bool radioactive_mutant_vampire;
//	...							
public:
        Bunny();	
	Bunny(Color c);		
        ~Bunny();		
	void showBunny();	// Display bunny info
//      ...
};
#endif 

I'm confident that creating a NameList object in Bunny is a bad design, because it creates a new, identical list every time a Bunny object is created. But I don't know where the NameList should be created instead. I only want one name list in the program so it seems reasonable to add it to main(), but then I can't use nameList.getRandomName() inside the Bunny constructor.

One option is to pass nameList as an argument to Bunny() constructor, but I don't really want the rest of the program to be responsible for that. I feel like it's possible to allow Bunny() constructor to simply call getRandomName(), but don't know how to make that happen. I've read up a bit about singleton classes, static classes and namespaces but don't really understand when they are and are not appropriate. Any advice would be greatly appreciated!

- David G. / EtDecius
closed account (Dy7SLyTq)
just make it static. it will then make one object to be shared across each instance
Thanks DTSCode, that seems reasonable but leaves another question.

Should the Bunny class create a static NameList member, or should the NameList class itself be static? (I don't even know if that second part is possible).

- David G. / EtDecius
closed account (Dy7SLyTq)
i would just make the member static. if you make the class static its still going to create a new instance of it each time i believe
You should use a standard container in place of a NameList class. Alternatively, you could roll your own generic container class and use it to store the names, but a NameList class (which is basically a container of strings?) doesn't seem like a terribly useful abstraction - we would rather have a container class which can be reused to store other things.

Making that container a static member of the bunny class seems like a reasonable design choice to me, however it might make more sense to not make it a member at all and declare/define the container within the source file for the bunny class (presumably bunny.cpp) as there is no reason for it to be visible to any code outside the class or anyone casually inspecting the header file.
Alright, I think I was able to get it to work.

Ran in to some trouble initializing the static NameList object, but finally got it to work by adding this line to the Bunny.cpp file: NameList Bunny::nameList = NameList();

That caused problems with the NameList class itself and, for reasons beyond my understanding, invalidated a static const string I was using to store the file name. So rather than keeping it static const, I just made the file name a normal member and initialized it in the constructor.

Anyhow, the program is now creating only one NameList regardless of how many bunnies are created. Success! Thanks again, good sir.

- David G. / EtDecius
@cire
Thanks for the feedback. I hadn't considered using a standard container for the name list since I don't have much practice with the STL library yet. My custom class ended up just being a dynamically-allocated array of strings, but I can already see the inefficiencies in the design. In particular, the class loops through the file twice (1st to count lines, 2nd to load values). A linked list or vector is probably a better idea, as it should be able to allocate space and assign values in a single loop through the file. This will be good practice to improve the code.

As for separating the Bunny and NameList classes, my goal was to boil components down in to pieces that are as small as possible. I (and probably a lot of new programers) tend to write massive functions and classes that do too much. I'm still unclear about how to divide program responsibilities into classes, so I'm keeping them as simple as possible for now.

- David G. / EtDecius
Topic archived. No new replies allowed.