VC++ OO code

elstcb
elstcb used Ask the Experts™
on
Hey ppl.

I've been given some C++ code and asked to make it Object Orientated, however having never done OO stuff before I have no idea what classes to break the code in to, the only hint I have is that there's going to be 3+ classes. I'm fine with the coding once I have the classes defined.

Any suggestions for how to break it up?

Thanks, Steve.


----------------------------------------------------------
Original code (OO version also needs load and save adding to it):



// Purpose
// A program to demonstrate the application of a simple digital filter
//
//
// Overview
// A sequence of data items and digital filter values need to be entered by the user.
// The application of the filter to the data involves a simple convolution operation.
// So that a number of filtering operations can be performed, the program allows the
// data and filter values to be overwritten during the program run. Also, so that
// multiple filtering of the data can be carried out, the filtered data overwrites
// the original data.
//
// The program checks the following
// 1. The data and filter values must have been entered before the filter is applied
// 2. The data and filter values must have been entered before the filtered data is
//    displayed
// 3. The filter is not applied if the number of filter values is greater than the
//    data values
//
// Example
//  before filtering:
//   data = [0 1 3 6 3 1 0]
//   filter = [-0.5 1 -0.5]
//  after filtering:
//   data = [-0.5 -0.5 3 -0.5 -0.5]
                                                           
#include <iostream>
using namespace std;
 
// the data values and the filter
struct TheData {
  double* Values;  // holds the data to be filtered
  unsigned long Length;  // number of data values
  bool Entered;   // true if the data values have been entered by the user
};

struct TheFilter {
  double* Values;   // the filter values
  unsigned long Length;  // number of filter values
  bool Entered;   // true if the filter values have been entered by the user
};

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

// function prototypes
void EnterData(TheData&);
void EnterFilter(TheFilter&);
int ApplyFilter(TheData&, TheFilter);
void DisplayData(TheData);
 
// Control the principal operations of the program
// Arguments: None
// Returns: 0 on completion
int main()
{
  // define the data and its initial values
  TheData Data = {0,0,false};
 
  // define the filter and its initial values
  TheFilter Filter = {0,0,false};

  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':
        EnterData(Data);
        Data.Entered = true;
        break;

      case '2':
        EnterFilter(Filter);
        Filter.Entered = true;
        break;      
 
      case '3':
        if (Data.Entered == true && Filter.Entered == true) {
          if (ApplyFilter(Data,Filter) == FILTER_TOO_LONG)
          {
            cout << "The filter must not be longer than the data" << endl;
          }
        }
        break;

      case '4':
        if (Data.Entered == true && Filter.Entered == true) {
          DisplayData(Data);
        }
        break;

      case '5':
        delete [] Data.Values;
        delete [] Filter.Values;
        return 0;
        break;

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


// Allow the user to enter the data
// Arguments:
//   (1) the data structure
// Returns: nothing
//
void EnterData(TheData& GetData)
{  
  // free any memory already allocated to the data
  delete [] GetData.Values;
 
  // get the number of data values from the user
  cout << "How many data values do you wish to enter: ";
  cin >> GetData.Length;

  // allocate memory to the data
  GetData.Values = new double[GetData.Length];
  if (GetData.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 < GetData.Length; CountData++) {
    cout << "Enter value " << CountData+1 << ": ";
        cin >> GetData.Values[CountData];
  }
}


 
// Allow the user to enter the filter values
// Arguments:
//   (1) the filter structure
// Returns: nothing
//
void EnterFilter(TheFilter& GetFilter)
{  
  // free any memory already allocated to the data
  delete [] GetFilter.Values;
 
  // get the number of filter values from the user
  cout << "How many data values do you wish to enter: ";
  cin >> GetFilter.Length;

  // allocate memory to the filter values
  GetFilter.Values = new double[GetFilter.Length];
  if (GetFilter.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 < GetFilter.Length; CountData++) {
    cout << "Enter value " << CountData+1 << ": ";
    cin >> GetFilter.Values[CountData];
  }
}


// Apply the filter to the data
// Arguments:
//   (1) the data structure
//   (2) the filter structure
// Returns: OK - if the filter is applied
//          FILTER_TOO_LONG - the filter is longer than the data
// Note: The array holding the data is resized to match that of the filtered data
//  
int ApplyFilter(TheData& Data, TheFilter Filter)
{  
  // return an error if the filter is longer than the data
  if (Filter.Length > Data.Length) return FILTER_TOO_LONG;
 
  // create a temporary structure to hold the new filtered data
  TheData FilterData;
  FilterData.Length = Data.Length - Filter.Length + 1;

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

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

  // release data memory
  delete [] Data.Values;

  // copy into the original data array
  Data.Length = FilterData.Length;
  Data.Values = FilterData.Values;

  return OK;
}


// Display the data
// Arguments:
//   (1) the data structure
// Returns: nothing
//
void DisplayData(TheData Data)
{  
  // display all of the data values
  cout << endl;
  cout << "The data values" << endl;
  cout << "---------------" << endl;
  cout << "[ ";
  for (unsigned long CountData = 0; CountData < Data.Length; CountData++) {
    cout << Data.Values[CountData] << " ";
  }
  cout << "]" << endl;
}
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Homework.

Author

Commented:
Coursework actually - and I've been stuck on it for far too long already!

Author

Commented:
Coursework actually - and I've been stuck on it for far too long already!
Exploring SharePoint 2016

Explore SharePoint 2016, the web-based, collaborative platform that integrates with Microsoft Office to provide intranets, secure document management, and collaboration so you can develop your online and offline capabilities.

Author

Commented:
BTW I don't expect the coursework doing for me - just a hint to get me out of a hole, I could do it but I'm not sure I'd be doing it right at the moment.
To begin with,

>> struct TheData {
>>  double* Values;  // holds the data to be filtered
>>  unsigned long Length;  // number of data values
>>  bool Entered;   // true if the data values have been entered by the user
>> };

>> struct TheFilter {
>>  double* Values;   // the filter values
>>  unsigned long Length;  // number of filter values
>>  bool Entered;   // true if the filter values have been entered by the user
>> };

translate these into classes. Once you have done this and the program works, without any structures, the code will then be object oriented. Structs are a holdover from the C language which was structure oriented. The main advantage of objects are that they can contain methods in addition to variables. These objects can then be serialized and sent over the internet, written to disk, and loaded back into memory.

Author

Commented:
Hi thanks for answering.

I'm somewhat confused as to why there were two structures in the first place as they hold the same information, so was planning on making one class but creating two objects (making the code neater) but this goes against the idea of "real world" items I guess.

I figured that the data object(s) should contain:
  * create
  * delete
  * resize
  * getsize
  * Maybe overloads for <<, >>, etc (or equivelents)
  * Maybe load and save

The other object I thought of was a filter object allowing you to apply the filter, maybe put load and save in here instead. That's kinda where I got confused...!

Steve

Author

Commented:
Ok now pretty sure I just got so confused because I wanted to combine the two data structs into one class and was looking for 2 more instead of 1 (where I couldn't see a clean split to make 3!).

Steve

Commented:
the basic idea of OOP in C++ is to represent real life object as class with data and operations.
look for a good book in C++ ,which will help u to understand the concept.
n.b if it is necessary that somone must transalate u code to C++ feel free to e-mail me at rmnganya@yahoo.com.
For Knowledge is there to be shared.
>> ...if it is necessary that somone must transalate u code to C++...

His code is in C++. He simply needs to translate structures to classes and a few other odds and ends. :-)

Author

Commented:
Thanks Exceter! Yeah I understand that it's supposed to be real world objects, however we have such a cr***y example as coursework that it's more confusing than a real program would be!

As for the good book, I have one thanks, but that hadn't solved my confusion. As it stands I think the main confusion was that I was trying to combine filter and data into one class even though they are two seperate items.

I'm hopeing to have some code knocked together in the next few days... at which point I'll see how confused I still am!

Steve

Author

Commented:
Ok still not 100% with this - I wont post all the code I've written unless requested but can you have a look at the following and tell me if it looks sensible?

class TheData
{
     public:
          TheData(unsigned long=0);
          ~TheData();
          Resize(unsigned long=0);
          GetLength();
          SetData(unsigned long, double);
          GetData(unsigned long);
          SetEntered(bool);
          GetEntered();
     private:
          double*               Values;
          unsigned long     Length;
          bool               Entered;
};

class TheFilter
{
     public:
          TheFilter(unsigned long=0);
          ~TheFilter();
          Resize(unsigned long=0);
          GetLength();
          SetData(unsigned long, double);
          GetData(unsigned long);
          SetEntered(bool);
          GetEntered();
     private:
          double*               Values;
          unsigned long     Length;
          bool               Entered;
};

class FilterFuncs
{
     public:
          EnterData(TheData&);
          EnterFilter(TheFilter&);
          ApplyFilter(TheData&, TheFilter);
          DisplayData(TheData);
          SaveData(TheData, TheFilter);
          LoadData(TheData&, TheFilter&);
     private:
};

Thanks,

Steve
>> class FilterFuncs
>> {
>>     public:
>>          EnterData(TheData&);
>>          EnterFilter(TheFilter&);
>>          ApplyFilter(TheData&, TheFilter);
>>          DisplayData(TheData);
>>          SaveData(TheData, TheFilter);
>>          LoadData(TheData&, TheFilter&);
>>     private:
>> };

This is the only part of this that I would question. I do not think that these functions should be in a class, why permit multiple instances of them? Do not get me wrong, this will work. I simply think that it is unecessary.

Author

Commented:
I agree - but we've been told that there should be no normal functions other than main in the program, so without sticking them all in a class I'm not sure what to do with them.

I guess it's always possible that you might want to use more than one filter at some point...?

Steve

Author

Commented:
Thanks for the help :-)
>> I guess it's always possible that you might want to use more than one filter at some point...?

Yes but since these functions accept pointers to instances of TheData and TheFilter the same functions can handle any number of either class. You simply pass it the pointer. The functions do not care which instance it is.

However, if it is required that you have no other functions I would recommend sticking the code for these functions in the main method. In the example you gaved each function is called in only one place so you can simply scratch the functions and place the code there.

Failing that I suppose you could use the class you posted but I would not recommend it for two reasons. First, it is a bad programming practise and, second, I do not think that the instructor intends that you hide these methods inside a class.

Author

Commented:
wow looks like I was a bit too hasty awarding points, but they were yours anyway :-)

Ok we basically got told that there should be no normal functions other than main, and that the instructor is expecting at at least 3 classes, which brings me back to my original confusion of why we need 3 classes at all and what they should be.



  "The objective of this task is to become familiar with the differences between structured and object-oriented approaches, particularly concentrating on the appropriate use of encapsulation and inheritance." (Requirements)

I don't feel like I've acheived encapsulation too well right now, and have no inheritance?!



  "Proper use of encapsulation, principally to implement an object-oriented structure which ensures that objects are responsible for performing calculations on their own data." (Marking scheme)

I'm now thinking that each filter object should have a "TheData" object and a "TheFilter" object rather than creating them in main?



  "appropriate use of constructors, destructors and
member functions."

I can't get delete [] to work from the FilterFuncs member functions at the moment... would that work if TheData/TheFilter objects were members of FilterFuncs?


A once again confused Steve :-(

Author

Commented:
Actually I take it back about the encapsulation, now I look at it again I think it's ok!

Author

Commented:
I'm guessing the inheritance should look like:

         Filter
         /    \
       /        \
     /            \
TheFilter      TheData

?????????

I don't really see that that acheives me much though (apart from being able to share enter, save, load, display functions - which I'm not sure is a good idea anyway).

I've have however decided that this coursework is stupid!

Steve
>> I can't get delete [] to work from the FilterFuncs member functions at the moment... would that work if TheData/TheFilter objects were
>> members of FilterFuncs?

You are having trouble because you made the double variable values a private member of both TheFilter and The data. This means that it can only be accessed from within the class. It can only be accesed from outside the class via a set or get method. It worked with your structs because they have no such access restrictions. The same could be achieved by making these variables public but I would not recommend it.

>> "appropriate use of constructors, destructors and member functions."

You use all of these in your TheData and TheFilter classes.

>> I don't feel like I've acheived encapsulation too well right now, and have no inheritance?!

Were you instructed to use inheritence? If so this would explain how you could have 3+ classes. I would do this by creating a class called data which would contain the following variables.

double* Values;
unsigned long Length;
bool Entered;

You would, of course, remove these variables from your other classes. You should then have both TheData and TheFilter inherit from class data.
>> I've have however decided that this coursework is stupid!

Course work usually does make you create very exacting programs that serve no usefull purpose. The purpose behind it is to teach the principles involved so that you can utilize the various capabilities of the language when you do try to write somthing.

Author

Commented:
 "Course work usually does make you create very exacting programs that serve no usefull purpose."
Yeah true, any more complicated and most people wouldn't stand a chance of doing it!

with the delete [] bit, I call a member function of TheData/TheFilter (in resize) but when called from FilterFuncs doesn't work, but from main does.

Inheritance is on the marking scheme, but only as "appropriate use of". That doesn't necessarily mean it has to be used (if it's not appropriate) but as we've been taught it and it's mentioned it's probably a good idea. Appropriate use of "call by value" is also on there but doesn't get used.

Bearing in mind that TheData and TheFilter are currently identical (as the structures were in the original) I could just inherit both to one object which I was originally planning to do, but then it seems silly having 2 objects. As you suggest I could inherit the private variables, I could also inherit the public functions as well though.

I don't think the instructor wants the normal functions putting in main, but I could put some of them (like enter, display, etc.) in the Data class that you suggest... That would really only leave the actual ApplyFilter function to do something with.

I'd go and speak to the instructor, but he doesn't give much help as the way to go about it, only on the syntax itself. I had a friend go and see him and he basically told him he was wrong and to go and re-read his notes! Not much help at all.

Apologies for dragging this out so much,

Steve
>> Yeah true, any more complicated and most people wouldn't stand a chance of doing it!

In my experience most people do not even try, but in actuallity they could do it if they applied their mind.

Okay, what do you think of this,

class Data
{
    public:
         Data(unsigned long=0);
         ~Data();
         Resize(unsigned long=0);
         GetLength();
         SetData(unsigned long, double);
         GetData(unsigned long);
         SetEntered(bool);
         GetEntered();
    private:
         double*               Values;
         unsigned long     Length;
         bool               Entered;
};

Then you create TheData and TheFilter to inherit from class data. Then you move the functions from FilterFuncs into the class which they apply. EnterFilter would go into TheFilter and EnterData into TheData, for example. However, since these functions accept pointers you can declare the classes as static, meaning that no matter how many instances of the class you created there would be only one copy of the static functions that would be used by all instances of that class. This satisfies the the requirements of inheritence, not having functions other than main, you have three classes, and you avoid the duplicity of the FilterFunc class.

Author

Commented:
Wow that's great, you see I'd have never of thought of putting it like that hence me asking for help in the first place! I'll give it a go and let you know how I get on.

Steve

Author

Commented:
Ok looking pretty cool so far, only problems are:

  *  Where to put ApplyFilter
  *  I'd like to Load/Save TheFilter and TheData at the same time - therefore need a home for these as well.
  *  Data::Data(unsigned long=0) sets the initial length of the Values array, however now when called by doing TheData Data(4) it doesn't work :-(

I've just found an inheritance tree I drew ages ago and it's starting to look pretty similar but I couldn't work out where to put the remaining 3 functions then either.

Author

Commented:
Just had a thought, could I override the * function to perform the ApplyFilter function? e.g.
  Data = Data * Filter;

instead of:
  Data = ApplyFilter(Data, Filter);

or something like that, now I'm really confusing myself :-/

Author

Commented:
Maybe using friend functions could help too, just trying to think what else he's taught that might be expected.
>> SaveData(TheData, TheFilter);
>> LoadData(TheData&, TheFilter&);

What do these methods do? Load/Save objects to/from the hard disk?

As to the ApplyFilter method I would either place it in the TheData class, as it is that class' data that needs to be modified, or simply place its code into the main method.

Author

Commented:
Yeah SaveData and LoadData store the current data and filter values on the HDD.

If I put ApplyFilter in the TheData class then do I need to make it a friend to TheFilter or do I just pass the filter object to it? I haven't a clue on the best way to do this bit!

Thanks,

Steve
>> If I put ApplyFilter in the TheData class then do I need to make it a friend to TheFilter or do I just pass the filter object to it? I haven't a
>> clue on the best way to do this bit!

I would simply pass it a pointer to an object of class TheFilter. I.E. the same way it was used before except that now you do not need to pass it a pointer to an object of class TheData because it is a member function of that class.

Author

Commented:
Ok got that, I would have done it that way too but didn't know enough about friends to know if that was a better way of doing it.

As for Load / Save, I'm thinking of putting 2 member functions in Data that either create a line of data to output or take in a line of data and split it into values.

class Data
{
   public:
        Data(unsigned long=0);
        ~Data();
        Resize(unsigned long=0);
        GetLength();
        SetData(unsigned long, double);
        GetData(unsigned long);
        SetEntered(bool);
        GetEntered();
        LoadData(CString);
        SaveData();
   private:
        double*               Values;
        unsigned long     Length;
        bool               Entered;
};

Then for Load, main can open file, call Data.Load() member function passing getline, call Filter.Load() member function passing getline, close file. Similar for save. 4 lines for each in main would seem pretty tidy to me...

Cool, think I know where I'm heading again now. Thanks again, I'll post some more points for you in a bit (seeing as you didn't have to carry on helping me!)

Author

Commented:
hmmm 2nd thoughts, getline is a dumb idea, I'll pass a pointer to the file instead and get the load/save functions to read/write the data!

Author

Commented:
hmmmmmm ok, I just got to the ApplyFilter function - how am I supposed to create a new data object for the temporary data when it's of the same type inside a member function of the type it's trying to be...?!?!

class TheData : public Data
{
     public:
          void EnterData();
          void DisplayData();
          int  ApplyFilter(TheFilter);
     private:
};

int TheData::ApplyFilter(TheFilter Filter)
{
     TheData TempData;
     TempData.Resize(GetLength() - Filter.GetLength() + 1);
        ...
}

I can think of several ways around it straight away, but none of them are very nice:
   1) Store the values in a temporary array, not an object
   2) Create another object in main and pass a pointer to that as well (kinda defeats the point a bit - unless I can force )
   3) As suggested before stick the apply filter into main (I don't think the guy who set it had that in mind).

There must be a better way...

Steve

Author

Commented:
  4) Put it inside the filter object, therefore removing the problem, but still a bit messy?

Author

Commented:
Exceter, there's some more points here for you, thanks for all the help!

Steve

http://www.experts-exchange.com/Programming/Programming_Languages/Cplusplus/qYourQuestion.jsp

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial