Please help me to convert a simple C++ program into an object-oriented one.

Please support our C++ advertiser: Programming Forums - DaniWeb Sister Site
Reply

Join Date: Jul 2005
Posts: 1,761
Reputation: Lerner is a name known to all Lerner is a name known to all Lerner is a name known to all Lerner is a name known to all Lerner is a name known to all Lerner is a name known to all 
Solved Threads: 283
Lerner Lerner is offline Offline
Posting Virtuoso

Re: Please help me to convert a simple C++ program into an object-oriented one.

 
0
  #11
Jan 1st, 2008
Duos:

I think you are being too restrictive in your interpretation of the problem set.

>>I don't think you should be introducing new structures into the assignment.

In reading the problem set as posted I don't see where the number or name of classes to be used for the project is specified. In post #1 the project was described as:

"to convert a standard C++ program into an object-oriented one, using the principals of polymorphism, encapsulation and inheritance."

I see no restriction to creating new user defined types in that project description.

In post #6 the following restritction to the project did become available:

"the task stipulates that the main function can create the first object only."

My approach does fulfill both of the posted criteria, though I don't think they are necessarily the way I would write the program, as I've said before.

>>Particularly as the FilterProgram is, as you have suggested it, simply a stand-in for main().

I disagree. FilterProgram::run() is the substitute for main(), not the FilterPrgam header file as such. Leaving run() out of FilterProgram and leaving all the menu's etc in main() would be just fine by me, though forcing everything into a user defined type is educational, and as long as distorting reality for purposes of education is part of the process, then so be it.

>> don't shuffle creation of things off into another function just to avoid doing it in main().

Agreed. However, the reason to do it us to allow me to reuse FilterProgram as a header file in another program so I don't have to rewrite:

TheData data;
TheFilter filter;
TheData filteredData;

I'll only need to write

FilterProgram program;

and instead of including two header files I'll only need to include one. Minor conveniences for simple programs, but techniques that seem to be used for many commercial header files. In this case I don't think FilterPrgram would be a header file I'd reuse again becuase it's too contrived, but it is the tecnique underlying the creation of FilterProgram that's important here, not FilterProgram itself.

>> how are the filter and the filtered data to be displayed alongside the original data?

In post #9 I clearly give TheData and TheFilter the capacity to display themselves.

>>how are the second piece of primary data (which I presume would be the filter) and the secondary data (the filtered data) to be generated and stored?

The data storage in the user defined types would be the same as in post #1. As I indicated in post #9 the user types posted need to be significantly fleshed out.

The filtered data would be generated by FilterProgram::applyFilter(). Again the declaration and definition need to be fleshed out. The posted code is exemplary of an idea only, not workable source code.

Trying to force the original program, which I agree looks fine to me as it stands, into an OOP style is a contrived situation and I suspect (hope?) is purely for educational purposes only.
Reply With Quote Quick reply to this message  
Join Date: Oct 2007
Posts: 1,953
Reputation: Duoas has much to be proud of Duoas has much to be proud of Duoas has much to be proud of Duoas has much to be proud of Duoas has much to be proud of Duoas has much to be proud of Duoas has much to be proud of Duoas has much to be proud of 
Solved Threads: 214
Featured Poster
Duoas's Avatar
Duoas Duoas is offline Offline
Posting Virtuoso

Re: Please help me to convert a simple C++ program into an object-oriented one.

 
0
  #12
Jan 1st, 2008
Lerner, you are assuming too much and hijacking this thread from the OP's question in an attempt to battle me. You have presented a solution. I have presented a similar train of thought. Now the OP needs to look at his homework assignment and make a decision as to how he will proceed, based on his knowledge of the problem set. Since neither you nor I know anything about the problem set other than what the OP has told us (which isn't much!), we are hardly in a position to give authoritative advice on how to interpret it.

Just because the OP, or his professor, did not prohibit x, y, and z, does not mean that we here should encourage the use of x, y, or z in his program. That is the professor's perogative. Not ours. It is too often the case that, in an effort to help, people lead beginners into things that are not part of the assignment, which is always an intentionally limited subset of programming, and thereby distract the beginner from the thing the professor expects him to be working on and learning about.

You are misunderstanding me, as you have taken pains to disagree with me about things for which we had both suggested, and you are misrepresenting my concerns. Please stop. If you really feel slighted, take it to PM and stop toasting here. I'll warn you though, I have a very comprehensive knowledge about program transformation.

Lastly, from what we do know of the assignment, it is "to force the original program ... into an OOP style"; specifically "to convert a standard C++ program into an object-oriented one". Deprecative vocabulary doesn't change things. I have already noted that his menu structure may have been of his own doing and not part of the original assignment. But at this point that is purely conjecture.
Reply With Quote Quick reply to this message  
Join Date: Dec 2007
Posts: 10
Reputation: zekesteer is an unknown quantity at this point 
Solved Threads: 0
zekesteer zekesteer is offline Offline
Newbie Poster

Re: Please help me to convert a simple C++ program into an object-oriented one.

 
0
  #13
Jan 3rd, 2008
Thank you both for your help. To clear things up, I've attached the stipulations of the task below:

Before writing your code you will need to think carefully about the following (HINT: these are hints!).

1. Decide on the classes you need. You should also be careful to include a set of classes that
implement the functionality of the code in such a way that they could be used by other
developers.

2. To establish suitable member functions, take into account the responsibilities of each class; for
example, which class should perform the filtering operation?

3. Encapsulation dictates that, as far as possible, an object should be responsible for its own data.
4. Use polymorphism only as appropriate. The general rule is that if an inbuilt operator matches
the purpose of a member function then it should be overloaded.

5. Use inheritance only where necessary. Only if you can reasonable say that object A is a type of
object B should A inherit from B. For example, a car is a type of vehicle, but a table isn’t a type
of elephant (even if both have four legs).

The following also forms part of the specification (for both the part B and part C modules).

1. The program must use an object-oriented approach; it must contain only member functions
(other than main() which should do no more than create the first object).

2. All members must be private.

3. Document properly the code you add. Don’t document every line of code - just the major
blocks of code (see the marking scheme).

4. The structure of your code should be neat and easy to follow.
Reply With Quote Quick reply to this message  
Join Date: Dec 2007
Posts: 10
Reputation: zekesteer is an unknown quantity at this point 
Solved Threads: 0
zekesteer zekesteer is offline Offline
Newbie Poster

Re: Please help me to convert a simple C++ program into an object-oriented one.

 
0
  #14
Jan 3rd, 2008
Hi Duoas,

I'm not sure I understand one part of your assignment. You stated that you are only allowed to directly instantiate one object.
My apologies for not being more forthcoming with the stipulations of the task. From my understanding, main() can only instantiate one object; this object can then go on to instantiate the remaining objects.
Reply With Quote Quick reply to this message  
Join Date: Dec 2007
Posts: 10
Reputation: zekesteer is an unknown quantity at this point 
Solved Threads: 0
zekesteer zekesteer is offline Offline
Newbie Poster

Re: Please help me to convert a simple C++ program into an object-oriented one.

 
0
  #15
Jan 3rd, 2008
My progress so far. The two areas that I'm having difficulty with are those that Lerner and Duoas have been (heatedly!) discussing; namely, outsourcing the code in main() and implementing the ApplyFilter() function using the best possible approach.

Please note that:

1. For simplicity, I've instantiated all objects within main() for the time being. The task requires that main() instantiate the first object only, so this must be changed.

2. I toyed with the idea of having the ApplyFilter() function read and write to the private members of the TheData class using the SetValue() and ShowValue() functions respectively. This seemed a pretty clumsy approach so I aborted half-way through. The functions remain but can be ignored.

Please continue to share your comments and suggestions!

Thanks,

Zeke

#include <iostream>
using namespace std;

// ------CLASS DEFINITIONS------

class TheData 
{
public:								
	TheData(double* = 0, unsigned long = 0, bool = false);			
	~TheData();						

	void SetValue(double*, TheData&);
	void SetValue(unsigned long, TheData&);
	void SetValue(bool, TheData&);

	double* ShowValue_Values();
	unsigned long ShowValue_Length(); 
	bool ShowValue_Valid();

	void EnterData(TheData& OriginalData);				
	void DisplayData(TheData OriginalData, TheData FilteredData) const;	
private:							
	double* Values;						
	unsigned long Length;						
	bool Valid;							
};

class TheFilter
{
public:
	TheFilter(double* = 0, unsigned long = 0, bool = false);		
	~TheFilter();						
	
	void EnterFilter(TheFilter& Filter);					

	void SetValue(double*, TheFilter&);
	void SetValue(unsigned long, TheFilter&);
	void SetValue(bool, TheFilter&);

	double* ShowValue_Values();
	unsigned long ShowValue_Length(); 
	bool ShowValue_Valid();

	int ApplyFilter(TheData OriginalData, TheFilter Filter, TheData& FilteredData);
	void DisplayData(TheFilter Filter) const;				
private:								
	double* Values;						
	unsigned long Length;						
	bool Valid;							
};

/*class PrivateData : public TheData, public TheFilter
{
public:
	double* Values;																
	unsigned long Length;														
	bool Valid;	
};*/

enum {OK,FILTER_TOO_LONG};		// Function return values

// ------------MAIN------------

int main()
{
	// main() to create the first object only!
	TheData OriginalData;						TheData FilteredData;							TheFilter Filter;											
	OriginalData.EnterData;						OriginalData.DisplayData;											
	char UserInput;

	// loop until the user wishes to exit
	while (1) {
	    
		// show the menu of options
		cout << endl;
		cout << "Filter Menu" << endl;
		cout << "-----------" << endl;
		cout << "1. Enter data for filtering" << endl;
		cout << "2. Enter filter values" << endl;
		cout << "3. Apply filter" << endl;
		cout << "4. Display filtered data" << endl;
		cout << "5. Exit from the program" << endl << endl;
	    
		// get the user's choice
		cout << "Enter your option: ";
		cin >> UserInput;
		cout << endl;
	    
		// act on the user's input
		switch(UserInput) {
		case '1':
			OriginalData.EnterData(OriginalData);
			FilteredData.SetValue(false, OriginalData);		
			break;

		case '2':
			Filter.EnterFilter(Filter);
			FilteredData.SetValue(false, FilteredData);
			break;      
	 
		case '3':
			if (Filter.ShowValue_Valid() == true && OriginalData.ShowValue_Valid() == true && FilteredData.ShowValue_Valid() == false) 
			{
				if (Filter.ApplyFilter(OriginalData, Filter, FilteredData) == FILTER_TOO_LONG) 
				{
					cout << "The filter must not be longer than the data." << endl;
				}
				else 
				{
					FilteredData.SetValue(true, FilteredData);
					cout << "Filter applied." << endl;
				}
			}
			break;

		case '4':
			if (Filter.ShowValue_Valid() == true && OriginalData.ShowValue_Valid() == true && FilteredData.ShowValue_Valid() == true) 
			{
				OriginalData.DisplayData(OriginalData, FilteredData);
				Filter.DisplayData(Filter);
			}
			else 
			{
				cout << "Data have not yet been filtered" << endl;
			}
			break;

		case '5':
		/*delete [] Filter.Values;
			delete [] OriginalData.Values; UNSURE WHAT TO DO HERE!
			delete [] FilteredData.Values;*/					return 0;
			break;

		default:
			cout << "Invalid entry" << endl << endl;
			break;
		}
	}
}

// --THEDATA MEMBER FUNCTIONS--

TheData::TheData(double*, unsigned long, bool)
{
	Values = 0;
	Length = 0;		
	Valid = false;						
}

TheData::~TheData()																// TheData destructor function
{
	/*delete[] OriginalData.Values;					
	delete[] OriginalData.Length;
	delete[] OriginalData.Valid;
																					// Free memory
	delete[] FilteredData.Values;
	delete[] FilteredData.Length;
	delete[] FilteredData.Valid;*/
}

void TheData::EnterData(TheData& OriginalData)
{
	// initialize the data structure that holds the data to be filtered, including getting
	// the number of data values from the user
	delete[] OriginalData.Values;
	cout << "How many data values do you wish to enter: ";
	cin >> OriginalData.Length;
	OriginalData.Valid = true;

	// allocate memory to the data
	OriginalData.Values = new double[OriginalData.Length];
	
	if (OriginalData.Values == 0) 
	{
		cout << "Unable to allocate sufficient memory." << endl;
		exit(1);
	}

	// obtain all of the data values
	cout << endl;
	cout << "Enter the data values" << endl;
	cout << "---------------------" << endl;
	
	for (unsigned long CountData = 0; CountData < OriginalData.Length; CountData++) 
	{
		cout << "Enter value " << CountData + 1 << ": ";
		cin >> OriginalData.Values[CountData];
	}
}

void TheData::DisplayData(TheData OriginalData, TheData FilteredData) const
{
	// display all of the input data values
	cout << endl;
	cout << "The input data values" << endl;
	cout << "---------------------" << endl;
	cout << "[ ";
	
	for (unsigned long CountData = 0; CountData < *OriginalData.Values; CountData++) 
	{
		//cout << OriginalData.SetValue(OriginalData.Values[CountData], OriginalData) << " ";
	}
	
	cout << "]" << endl;
	
	// display all of the data output values
	cout << endl;
	cout << "The data output values" << endl;
	cout << "----------------------" << endl;
	cout << "[ ";

	for (unsigned long CountData = 0; CountData < FilteredData.Length; CountData++) 
	{
		//cout << FilteredData.SetValue(FilteredData.Values[CountData], FilteredData) << " ";
	}
	cout << "]" << endl;
}

void TheData::SetValue(double* SetValue, TheData& Original_or_Filtered_Data)
{
	Original_or_Filtered_Data.Values = SetValue;
}

void TheData::SetValue(unsigned long SetValue, TheData& Original_or_Filtered_Data)
{
	Original_or_Filtered_Data.Length = SetValue;
}

void TheData::SetValue(bool SetValue, TheData& Original_or_Filtered_Data)
{
	Original_or_Filtered_Data.Valid = SetValue;
}

double* TheData::ShowValue_Values()
{
return 0;
}

unsigned long TheData::ShowValue_Length()
{
return 0;
}

bool TheData::ShowValue_Valid()
{
return false;
}

// -THEFILTER MEMBER FUNCTIONS-

TheFilter::TheFilter(double*, unsigned long, bool)			
{
	Values = 0;		
	Length = 0;				
	Valid = false;	
}

TheFilter::~TheFilter()		
{
	// delete[] "something"?														// Free memory
}

void TheFilter::EnterFilter(TheFilter& Filter)
{
	// initialize the data structure that holds the filter, including getting the number of
	// filter values from the user
	delete [] Filter.Values;
	cout << "How many data values do you wish to enter: ";
	cin >> Filter.Length;
	Filter.Valid = true;

	// allocate memory to the filter values
	Filter.Values = new double[Filter.Length];

	if (Filter.Values == 0) 
	{
		cout << "Unable to allocate sufficient memory" << endl;
		exit(1);
	}

	// obtain all of the filter values
	cout << endl;
	cout << "Enter the filter values" << endl;
	cout << "-----------------------" << endl;

	for (unsigned long CountData = 0; CountData < Filter.Length; CountData++) 
	{
		cout << "Enter value " << CountData + 1 << ": ";
		cin >> Filter.Values[CountData];
	}
}

int TheFilter::ApplyFilter(TheData OriginalData, TheFilter Filter, TheData& FilteredData)
{
	// return an error if the filter is longer than the data
	if (Filter.Length > OriginalData.Length) return FILTER_TOO_LONG;
	
	// initialize the data structure that holds the filtered data
	delete[] FilteredData.Values;
	FilteredData.Length = OriginalData.Length - Filter.Length + 1;
	
	// get memory for the filtered data
	FilteredData.Values = new double[FilteredData.Length];
	
	if (FilteredData.Values == 0) 
	{
		cout << "Unable to allocate sufficient memory" << endl;
		exit(1);
	}

	// apply the filter to the data
	for (unsigned long CountData = 0; CountData < FilteredData.Length; CountData++) 
	{
		FilteredData.Values[CountData] = 0.0;
		
		for (unsigned long CountFilter = 0; CountFilter < Filter.Length; CountFilter++) 
		{
			FilteredData.Values[CountData] += OriginalData.Values[CountData + CountFilter] * Filter.Values[CountFilter];
		}
	}
	return OK;
} 

void TheFilter::DisplayData(TheFilter Filter) const
{
	// display all of the filter values
	cout << endl;
	cout << "The filter values" << endl;
	cout << "-----------------" << endl;
	cout << "[ ";
	
	for (unsigned long CountData = 0; CountData < Filter.Length; CountData++) 
	{
		//cout << Filter.SetValue(Filter.Values[CountData], Filter) << " ";
	}
	
	cout << "]" << endl;
}

void TheFilter::SetValue(double* SetValue, TheFilter& Filter)
{
	Filter.Values = SetValue;
	//cout << "Testing Values: " << Filter.Values << " = " << SetValue;	
}

void TheFilter::SetValue(unsigned long SetValue, TheFilter& Filter)
{
	Filter.Length = SetValue;
	//cout << "Testing Length: " << Filter.Length << " = " << SetValue;	
}

void TheFilter::SetValue(bool SetValue, TheFilter& Filter)
{
	Filter.Valid = SetValue;
	//cout << "Testing Valid: " << Filter.Valid << " = " << SetValue;	
}

double* TheFilter::ShowValue_Values()
{
	double* ShowValue;
	ShowValue = 0; //Filter.Values;	

	return ShowValue;
}

unsigned long TheFilter::ShowValue_Length()
{
	unsigned long ShowValue;
	ShowValue = 0; //Filter.Length;

	return ShowValue;
}

bool TheFilter::ShowValue_Valid()
{
	bool ShowValue;
	ShowValue = false; //Filter.Valid;

	return ShowValue;
}

P.S. Sorry that the code is pretty hard to read! I'll provide the .cpp file if required.
Reply With Quote Quick reply to this message  
Join Date: Oct 2007
Posts: 1,953
Reputation: Duoas has much to be proud of Duoas has much to be proud of Duoas has much to be proud of Duoas has much to be proud of Duoas has much to be proud of Duoas has much to be proud of Duoas has much to be proud of Duoas has much to be proud of 
Solved Threads: 214
Featured Poster
Duoas's Avatar
Duoas Duoas is offline Offline
Posting Virtuoso

Re: Please help me to convert a simple C++ program into an object-oriented one.

 
0
  #16
Jan 3rd, 2008
I haven't looked through your last posting too closely yet...

2 and related stuff
It appears that your teacher expects ApplyFilter() to be a member function of either TheData or TheFilter. You must choose one, and be able to justify your choice to the professor.

The ApplyFilter() function, however should never access private members of any foreign class. In other words, if it is TheData::ApplyFilter() then it should not access the private members of TheFilter. Likewise, if it is TheFilter::ApplyFilter() then it should not access the private members of TheData. Hopefully, thinking about this will help you choose which class should have the ApplyFilter() method.

The foreign class should only be accessed by accessor methods. In other words, to access any data element of TheData, write member functions
double TheData::getValue( int index )
and
void TheData::setValue( int index, double value )
This allows controlled access to TheData's data, and as part of the public interface, is OK to use anywhere. The same holds true for TheFilter.

inheritance
It appears from hint #5 that your teacher will not permit you to derive TheFilter and TheData from the same ancestor class. Just because they look similar is not sufficient to say that they are the same kind of thing.

Unless you can reasonably argue that they are, in fact, variations of the same thing.

1 and thoughts
Lerner suggests that you overcome the obstacle by creating a third class, which encapsulates the program and contains a member function ("run()") which creates two TheData and one TheFilter. This might be considered a way of satisfying hint #1. (I don't like it though, but that is my personal opinion.)

I still don't know if you must make your program interact with the user exactly like the original or not, but if not, you might work it this way:
  1. create the OriginalData object in main()
  2. the OriginalData object creates a Filter object and uses it to filter itself
There are things I dislike about this as well.

Remember, the professor wants you to make things friendly to "other developers" as well, so you will want to expose both the TheData and TheFilter classes. However, what this particular program does with them is, obviously, specific to this particular program, and does not need to be made particularly exportable for other users.

Thus, TheFilter and TheData should not have stuff in them that are specific to this program.

One solution might be something of a combination of our two ideas: which is to create another class which main() directly manipulates to create and filter data.

Hope this gives you some ideas.

Oh yeah, I don't see any reason why you would have to overload any operators.
Reply With Quote Quick reply to this message  
Join Date: Jul 2005
Posts: 1,761
Reputation: Lerner is a name known to all Lerner is a name known to all Lerner is a name known to all Lerner is a name known to all Lerner is a name known to all Lerner is a name known to all 
Solved Threads: 283
Lerner Lerner is offline Offline
Posting Virtuoso

Re: Please help me to convert a simple C++ program into an object-oriented one.

 
0
  #17
Jan 3rd, 2008
I do advocate using a third class, as I don't like the idea of the data modifying itself or the filter forcing itself on the data. Given the information in post #13 I would argue against deriving TheData and TheFilter from a common class and I wouldn't use a run() in the third class--both are way too contrived to fit the guidelines.

The following outline would cause the least distortion of reality in my view:
  1. class FilteredData
  2. private
  3. TheData data
  4. TheFilter filter
  5. double * filteredData
  6. public
  7. populate()
  8. applyFilter()
  9. display()
  10.  
  11. main()
  12. FilteredData fd
  13. fd.populate()
  14. fd.applyFilter()
  15. fd. display()

Though, given the relationship of a filtered set of objects and an unfiltered set of objects this might work as well:
  1. class TheFilteredData : public TheData
  2. private
  3. double * filteredData
  4. public
  5. applyFilter(TheFilter)

I would also consider implementing the objective of these:

double TheData::getValue( int index )

void TheData::setValue( int index, double value )

by overloading the [] operator given this statement in post #13

"The general rule is that if an inbuilt operator matches the purpose of a member function then it should be overloaded."

but then again that's just my thought.
Last edited by Lerner; Jan 3rd, 2008 at 9:19 pm.
Reply With Quote Quick reply to this message  
Join Date: Dec 2007
Posts: 10
Reputation: zekesteer is an unknown quantity at this point 
Solved Threads: 0
zekesteer zekesteer is offline Offline
Newbie Poster

Re: Please help me to convert a simple C++ program into an object-oriented one.

 
0
  #18
Jan 8th, 2008
Thank you both for your help and advice. I now have the program working correctly although it still needs a great deal of refinement.

I favour Lerner's approach of a third class for the filtered data as it appears tidier and - if I inherit the member functions and private members from TheData as he suggested - it allows me to use inheritance. However, I recognise that I'm not necessarily trying to build the best program, but rather, the program which best meets the requirements set by my lecturer.

For the time being, I've made ApplyFilter() a member function of the TheData class (as Duoas suggested), accessing TheFilter's private members through the ShowValue and SetValue member functions. As you both know, my experience with objects is limited and I'm unsure if this is the best approach (Duoas says yes, Lerner says no). It'd be wonderful if you could both agree on whether or not the creation of a separate FilteredData class would best meet the task criteria set by my lecturer! I'd much rather obtain the highest possible marks than build the best possible program.

I'm also a little unsure about the constructor functions. EnterData() and EnterFilter() each allocate memory (using "new") for the "values" members in their respective classes. Would a better approach not be to have the memory allocated within the TheData and TheFilter constructor functions instead? The only problem with this is that the number of data and filter values aren't known until EnterData() and EnterFilter() are actually called, when the user is asked "How many data values do you wish to enter: "... Can either of you see anyway around this obstacle?

P.S. Lerner, please could you explain what you meant when you suggested overloading the [] operator?
Reply With Quote Quick reply to this message  
Join Date: Oct 2007
Posts: 1,953
Reputation: Duoas has much to be proud of Duoas has much to be proud of Duoas has much to be proud of Duoas has much to be proud of Duoas has much to be proud of Duoas has much to be proud of Duoas has much to be proud of Duoas has much to be proud of 
Solved Threads: 214
Featured Poster
Duoas's Avatar
Duoas Duoas is offline Offline
Posting Virtuoso

Re: Please help me to convert a simple C++ program into an object-oriented one.

 
0
  #19
Jan 8th, 2008
Lerner made a brilliant observation in noticing that the [] operator could be used to access data elements. See here for an example. And here. And here. You might want to change TheFilter's ShowValue and SetValue methods to use this subscript operator... (if you want).

I disagree that TheData and TheFilteredData should be separate classes (and I didn't get the impression that Lerner advocated it either...) simply because both hold the same kind of data: a list of values. Just because one has been transformed differently than the other doesn't change the specific characteristics of the data itself. No qualified professor will give you better marks for a poorly written program just to fit some perceived criterion. The best possible program best satisfies the program requirements. Make sense?

The constructor only needs to create and initialize the object so that it is usable in the sense that it can be handled without generating serious errors. That doesn't mean that it has to have all its data defined/allocated/whatever, or that it has to be of any actual use. You've thought about it correctly. Where, then, do you think is the best place to use new?

Hope this helps.
Reply With Quote Quick reply to this message  
Join Date: Dec 2007
Posts: 10
Reputation: zekesteer is an unknown quantity at this point 
Solved Threads: 0
zekesteer zekesteer is offline Offline
Newbie Poster

Re: Please help me to convert a simple C++ program into an object-oriented one.

 
0
  #20
Jan 8th, 2008
Hi Duoas and Lerner,

The program is almost complete and I’m very happy with it! Just the following issues remain:

1. The member function, ApplyFilter() currently reads:

int TheData::ApplyFilter(TheData OriginalData, TheFilter Filter, TheData& FilteredData)
{
	// return an error if the filter is longer than the data
	if (Filter.Length() > OriginalData.length) return FILTER_TOO_LONG;
	
	// initialize the data structure that holds the filtered data
	delete[] FilteredData.values;
	FilteredData.length = OriginalData.length - Filter.Length() + 1;
	
	// get memory for the filtered data
	FilteredData.values = new double[FilteredData.length];
	
	if (FilteredData.values == 0) 
	{
		cout << "Unable to allocate sufficient memory" << endl;
		exit(1);
	}

	// apply the filter to the data
	for (unsigned long CountData = 0; CountData < FilteredData.length; CountData++) 
	{
		FilteredData.values[CountData] = 0.0;
		
		for (unsigned long CountFilter = 0; CountFilter < Filter.Length(); CountFilter++) 
		{
			FilteredData.values[CountData] += OriginalData.values[CountData + CountFilter] * Filter.operator [](CountFilter);
		}
	}
	return OK;
}
I'd like ApplyFilter() to read something like this:

  1. int TheData::ApplyFilter()
  2. {
  3. // return an error if the filter is longer than the data
  4. if (Filter.Length() > length) return FILTER_TOO_LONG;
  5.  
  6. // initialize the data structure that holds the filtered data
  7. delete[] values;
  8. length = length - Filter.Length() + 1;
  9.  
  10. // get memory for the filtered data
  11. values = new double[length];
  12.  
  13. if (values == 0)
  14. {
  15. cout << "Unable to allocate sufficient memory" << endl;
  16. exit(1);
  17. }
  18.  
  19. // apply the filter to the data
  20. for (unsigned long CountData = 0; CountData < length; CountData++)
  21. {
  22. values[CountData] = 0.0;
  23.  
  24. for (unsigned long CountFilter = 0; CountFilter < Filter.Length(); CountFilter++)
  25. {
  26. values[CountData] += values[CountData + CountFilter] * Filter.operator [](CountFilter);
  27. }
  28. return OK;
  29. }
By removing the references to the OriginalData and FilteredData objects however, there is no way to differentiate between the members of OriginalData and FilteredData (values, length and valid). Does anyone know if what I’m trying to do is possible, or will I have to maintain the existing format?

2. Using the suggestion from Lerner and the links that Duoas provided, I've overloaded the [] operator to allow TheData::ApplyFilter() to access TheFilter::values. The code is shown below.

  1. class TheFilter {
  2. public:
  3. double& operator[] (unsigned int Index) {return values[Index];}
  4. const double& operator[] (unsigned int Index) const {return values[Index];}
  5. ...};
To access TheFilter::values from TheData::ApplyFilter(), I’m using the following statement: Filter.operator [](CountFilter). Is this correct? When I use the statement: Filter.values[CountFilter] I receive an error at compilation: “cannot access private member declared in class ‘TheFilter’.

3. I’m receiving a runtime error ”_BLOCK_TYPE_IS_VALID” when ApplyFilter() and DisplayData() are called, and when the program exits. I read online that this error is caused when the destructor functions are called twice in succession, so I commented out their bodies and the program runs fine. For example, for the TheFilter destructor:

  1. class TheFilter
  2. {
  3. public: ~TheFilter();
  4. }
  5.  
  6.  
  7. TheFilter::~TheFilter()
  8. {
  9. // delete[] values;
  10. }
However, I actually require the destructor functions. I need a way to address this runtime error whilst maintaining the functionality of the destructor functions.

4.
Where, then, do you think is the best place to use new?
I'd hazard a guess that the best place would be in the EnterFilter() and EnterData() member functions… am I correct?!

Zeke
Reply With Quote Quick reply to this message  
Reply

This thread is more than three months old.
Perhaps start a new thread instead?
Message:



Similar Threads
Other Threads in the C++ Forum


Views: 2693 | Replies: 22
Thread Tools Search this Thread



Tag cloud for C++
About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC