1,105,380 Community Members

Struct vs class

Member Avatar
Hey90
Junior Poster in Training
78 posts since Dec 2010
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

I would like to convert a procedural database program that I have created to an object oriented program. In my procedural program I use a struct:

struct shoes{

    char Name[20];
    int Number;
    double ShoeSize;
};

Putting this into a class would I simply use:

class Shoes{

public:

    //Function declerations

private:
    chat Name[20]
    int Number;
    double ShoeSize;

};

Originally I passed the struct between functions, for example:

void view(Shoes *Shoe);

Can I do the same with the class? would this pass all the variables or would I have to separetly pass each variable? if not what is the best way to pass these variables as a group while using classes? would it be normal to use a struct inside a class?

Member Avatar
deceptikon
Eternally Awesome
4,693 posts since Jan 2012
Reputation Points: 1,341 [?]
Q&As Helped to Solve: 688 [?]
Skill Endorsements: 104 [?]
Administrator
Featured
 
0
 

The only difference between struct and class in C++ is default visibility. Structures are public by default and classes are private. Other than that they're identical in features and functionality. Use whichever makes more sense to you.

Member Avatar
Hey90
Junior Poster in Training
78 posts since Dec 2010
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

I just have a problem when passing between functions:

class Shoes{

public:

    void Load(Shoes* Shoe);

private:
    char Name[20];
    int Number;
    double ShoeSize;

};

void Shoes::Load(Shoes* Shoe)
{

    //Code

}

int main()
{

    Shoes Shoe;

    Shoe.Load(Shoe);

}

I get an error with line 26 saying 'No viable conversion from Shoes to Shoes *'
Why is this?

Member Avatar
deceptikon
Eternally Awesome
4,693 posts since Jan 2012
Reputation Points: 1,341 [?]
Q&As Helped to Solve: 688 [?]
Skill Endorsements: 104 [?]
Administrator
Featured
 
0
 

A pointer to T and an object of T aren't compatible types. You can convert Shoe into a pointer, but that seems kind of silly since the member function is being called on Shoe...

Shoe.Load(&Shoe);
Member Avatar
mike_2000_17
21st Century Viking
4,085 posts since Jul 2010
Reputation Points: 2,259 [?]
Q&As Helped to Solve: 800 [?]
Skill Endorsements: 73 [?]
Moderator
Featured
Sponsor
 
0
 

what is the best way to pass these variables as a group while using classes?

By make the function a member function of the class. In the case of a function like:

void view(Shoes *Shoe);

The easiest way to do this in object-oriented code, is just as so:

class Shoes{
public:

    void view();

private:
    char Name[20]
    int Number;
    double ShoeSize;
};

And when you have an object like:

Shoes my_shoe;

You can simply call the member function like this:

my_shoe.view();

And because view() is a member function, a pointer to the object my_shoe is implicitely passed to the function. Inside the implementation of the view() function, you can access the data members either directly by name, or using the this pointer which is always pointing to the object on which the function was called. In other words, you can define the view() function like this:

void Shoes::view() {
  std::cout << Number << std::endl;
  std::cout << this->ShoeSize << std::endl;
};

In the above, when calling view() with my_shoe.view(), the variable Number refers to my_shoe.Number, and the variable this->ShoeSize equivalently refers to my_shoe.ShoeSize. This is really the whole point of having this so-called object-oriented syntax in C++, having the implicit passing of and reference to an instance of the class within member functions.

Member Avatar
Hey90
Junior Poster in Training
78 posts since Dec 2010
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

Ok thanks for the help. I have simply tried reading a text file with the shoe information in but the output is garbage. I have the following files:

Shoes.h:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

#ifndef Project1_Shoes_h
#define Project1_Shoes_h

class Shoes
{    
public:
    //Constructor
    Shoes();

    void View(Shoes* Shoe);  
    void Display(Shoes* Shoe);  

private:
    unsigned long length;
    char Name[10];  
    unsigned int Number;
    double ShoeSize;

};

#endif

Shoes.cpp:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

#include "Shoes.h"  

Shoes::Shoes()
{

}

void Shoes::Load(Shoes* Shoe)
{

    fstream input_file;  

    input_file.open("shoe_list.txt");

    // load length information from file
    if(input_file.good())
    {
        input_file >> length;

        for (unsigned long i=0; i<6; i++)
        {
            input_file >> Shoe[i].Name;
            input_file >> Shoe[i].Number;
            input_file >> Shoe[i].ShoeSize;
        }
    }

    input_file.close();
}

void Shoes::View(Shoes* Shoe)
{
    cout << length << endl <<endl;

    for (unsigned long i=0; i<6 ;i++)
    {
        cout << Shoe[i].Name << endl;
        cout << Shoe[i].Number << endl;
        cout << Shoe[i].ShoeSize << endl;
        cout << endl;
    }

}

main.cpp:

#include <iostream>
#include <fstream>
#include <string>

#include "Shoes.h"

using namespace std;

//#define MAX 50

int main()
{
    Shoes Shoe[MAX];

    char input;

    while (1) {
        cout << endl;
        cout << "Menu" << endl;
        cout << "(1) Load" << endl;
        cout << "(2) View" << endl;
        cout << "(3) Exit" << endl;

        cout << "Enter your option: ";
        cin >> UserInput;
        cout << endl; 

        switch(input) {
            case '1':
                Shoe.Load(&Shoe);
                break;
            case '2':
                Shoe.View(&Shoe);
                break;
            case '3':
                return 0;
            default:
                cout << "Invalid entry" << endl << endl;
                break;
        }
    }
    return 0;
}

shoe_list.txt:

6

Nike
2
7.5

Puma
4
6

Nike
4
8.5

Addidas
1
9

Puma
2
10

Reebok
1
11.5

The output result given after loading the file and then viewing it is just a load of garbage in place of how the data should appear. Could anyone help me? Is it to do with the way I am passing the variables?

Member Avatar
Lerner
Nearly a Posting Maven
2,416 posts since Jul 2005
Reputation Points: 579 [?]
Q&As Helped to Solve: 407 [?]
Skill Endorsements: 16 [?]
 
0
 

Hey, slow down tenderfoot. You seem to be moving so fast you're stumbling over your own feet.

Inclusion guards are great. I'm glad you know about them. However, they should go at the top of the file so you don't include std or fstream or other files multiple times if you are linking/including multiple files , in your program.

Syntax such as,

const int MAX = 50;

is preferred to

define int MAX 50;

It would also be preferrable for MAX to have some scope other than global, so I'd declare it is main() rather than before it. As posted, MAX has no value whatsoever, as the line declaring MAX is commented out.

I would tend to name the class Shoe rather than Shoes. That way I can use Shoes as the name of a container (in this case an array) of multiple instances of type Shoe. I like to have each type be able to display an instance of itself. I would use functions outside the type declare to accumulate a group of instances of the type and to display any, or all, of the instances belonging to that group of instances.

The file you are using has a value indicating how many instances of type Shoe are in the file. You should use the variable length, instead of literal int 6, when dealing with actual number of instances of type Shoe are actually in the array, for example in the loop used to load array when reading from the file.

Syntax such as,

const int MAX = 50;

is preferred to

define int MAX 50;

It would also be preferrable for MAX to have some scope other than global, so I'd declare it in main() rather than before it.

As posted, MAX has no value whatsoever, as the line declaring MAX is commented out.

The pointer parameter you are using refers to an array of type, not to a single instance of type. Typically, you would also send the size of the array and the actual number of elements in the array.

const int MAX = 50;
T t[MAX]; //declare an array of type T holding, at most, MAX number of instances of type T
int len = 6; //assume there are only 6 instances of type T in t.
void view(T* t, int len); //declaration of a function, outside of the class and global in scope, that displays an array of type T called t which has len instances of type T in it.

Here is an alternate syntax to declare a function called view to display the elements of type T contained in an array of type T called t that could hold MAX elements but actually has only len elements in it at this time.
void view(T t[MAX], int len);

The pointer verssion to decare view() is quicker to type, and would be preferred if t were declared using dynamic memory. The alternate version of view() is explicit in indicating that t is an array of type T, not a pointer to single instance, and that t could hold up to MAX elements, but actually only has len.

Member Avatar
Hey90
Junior Poster in Training
78 posts since Dec 2010
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

I put length equal to 6 as the program was printing garbage so it read in something like 345657 into length :-S

Making changes I now get some errors:

error C2228: left of '.Load' must have class/struct/union
          type is 'Shoes [50]'

and:

error C2065: 'length' : undeclared identifier

even though I have declared length in the class Shoes ...

Member Avatar
Moschops
Nearly a Posting Virtuoso
1,383 posts since Sep 2008
Reputation Points: 414 [?]
Q&As Helped to Solve: 269 [?]
Skill Endorsements: 16 [?]
Featured
 
0
 

Shoe is an array of 50 shoe objects. Is an array of 50 objects of type shoe the same thing as a single object of type shoe? No.
Can you call a class function of the shoe class on an object that is not an object of type shoe? No.

Member Avatar
Hey90
Junior Poster in Training
78 posts since Dec 2010
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

So would I simply call like this instead:

Shoe[MAX].Load(&Shoe)
Member Avatar
Hey90
Junior Poster in Training
78 posts since Dec 2010
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

Sorry I mean:

Shoe[i].Load(Shoe);
Member Avatar
Hey90
Junior Poster in Training
78 posts since Dec 2010
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

I realised after all this I didn't have the text file in the correct place......

Member Avatar
Hey90
Junior Poster in Training
78 posts since Dec 2010
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

The only other problem is that it says length is undeclared when I add it as a variable to pass in the functions, which I dont understand as it is declared in the shoes class in Shoes.h :-S does anyone know why this is?

Member Avatar
NathanOliver
Posting Virtuoso
1,657 posts since Apr 2009
Reputation Points: 284 [?]
Q&As Helped to Solve: 310 [?]
Skill Endorsements: 4 [?]
 
0
 

Can you post the relevent code?

Member Avatar
Hey90
Junior Poster in Training
78 posts since Dec 2010
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

Sure;

Shoes.h:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

#ifndef Project1_Shoes_h
#define Project1_Shoes_h

class Shoes
{    
public:
    //Constructor
    Shoes();

    void Enter(Shoes&, unsigned long&);
    void Load(Shoes*, unsigned long&);  
    void View(const Shoes*, unsigned long);  

private:
    unsigned long length;
    char Name[20];  
    unsigned int Number;
    double ShoeSize;

};


#endif

Shoes.cpp

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

#include "Shoes.h"  

Shoes::Shoes()
{
   Number = 0;
   ShoeSize = 0.0;
   length = 0;
}

void Shoes::Enter(Shoes& Shoe, unsigned long& length)
{
    cout << "Enter New Shoe" << endl;
}

void Shoes::Load(Shoes* Shoe, unsigned long& length)
{

    fstream input_file;  

    input_file.open("shoe_list.txt");

    if(input_file.good())
    {
        input_file >> length;

        for (unsigned long i=0; i<length; i++)
        {
            input_file >> Shoe[i].Name;
            input_file >> Shoe[i].Number;
            input_file >> Shoe[i].ShoeSize;
        }
    }

    input_file.close();
}

void Shoes::View(const Shoes* Shoe, unsigned long length)
{
    cout << length << endl <<endl;

    for (unsigned long i=0; i<length ;i++)
    {
        cout << Shoe[i].Name << endl;
        cout << Shoe[i].Number << endl;
        cout << Shoe[i].ShoeSize << endl;
        cout << endl;
    }

}

main.cpp

#include <iostream>
#include <fstream>
#include <string>

#include "Shoes.h"

using namespace std;

int main()
{
    const int MAX = 10;
    int i =0;
    Shoes Shoe[MAX];

    char input;

    while (1) {
        // show the menu of options
        cout << endl;
        cout << "Menu" << endl;
        cout << "1. Enter" << endl;
        cout << "2. Load" << endl;
        cout << "3. View" << endl;
        cout << "4. Exit" << endl << endl;

        cout << "Enter your option: ";
        cin >> input;
        cout << endl;

        switch(input) {
            case '1':
                Shoe[i].Enter(Shoe[length]);
                break;
            case '2':
                Shoe[i].Load(Shoe, length);
                break;
            case '3':
                Shoe[i].View(Shoe, length);
                break;
            case '4':
                return 0;
            default:
                cout << "No such choice" << endl << endl;
                break;
        }
    }
    return 0;
}

shoe_list.txt:

6

Nike
2
7.5

Puma
4
6

Nike
4
8.5

Addidas
1
9

Puma
2
10

Reebok
1
11.5

Member Avatar
NathanOliver
Posting Virtuoso
1,657 posts since Apr 2009
Reputation Points: 284 [?]
Q&As Helped to Solve: 310 [?]
Skill Endorsements: 4 [?]
 
0
 

I dont think you are implementing this correctly. You are trying to use class functions to take the place of global functiuons you used to have. If you dont change anything then it is not going to work. Take load() for example. If you want to load an array a shoes from a file you should have that as a global function since one shoe should not be responsible for populating an array of other shoes.

Member Avatar
Hey90
Junior Poster in Training
78 posts since Dec 2010
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

Im not quite sure what you mean. Do you mind explain a bit further?

Member Avatar
NathanOliver
Posting Virtuoso
1,657 posts since Apr 2009
Reputation Points: 284 [?]
Q&As Helped to Solve: 310 [?]
Skill Endorsements: 4 [?]
 
0
 

Something like this

// shoe should be a single object
class Shoe
{
public:
    Shoe() : name(""), shoeSize(0), number(0) {}
    Shoe(string _name, double _size, int _number) : name(_name), shoeSize(_size), number(_number) {}

    // getters
    string getName() const { return name; }
    double getSize() const { return shoeSize; }
    int getNumber() const { reutrn number; }

    //setters
    void setName(string _name) { name = _name; }
    void setSize(double _size) { shoeSize = _size; }
    void setNumber(int _number) { number = _number; }

private:
    string name;
    double shoeSize;
    int number;
};


// now we make a shoe list
class ShoeList
{
public:
    ShoeList()

    bool Load(string filename)  // use bool to signle if operation was succesful
    {
        // read in shoes and add them to the vector
    }
    void Display() const
    {
        for(int i = 0 i < shoes.size; i++)
            cout << shoes[i].display() << endl
    }
private:
    vector<Shoe> shoes
};

This way you have a ShoeList that manages all of the seperate shoes and the Shoe class just takes care of itself. You could also just do this with functions but if you are changing it to OOP then this should be the way you go.

Member Avatar
Hey90
Junior Poster in Training
78 posts since Dec 2010
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

What are the advantages of using a vector over an array?
I don't really understand setters and getters...I haven't been taught to use this. Im not sure what exactly they are doing but I shall read up on them.

Member Avatar
NathanOliver
Posting Virtuoso
1,657 posts since Apr 2009
Reputation Points: 284 [?]
Q&As Helped to Solve: 310 [?]
Skill Endorsements: 4 [?]
 
0
 

I like a vector because it is scalable so you don’t need to know what the size is ahead of time. It really is a matter of preference but it also keeps with the OOP side of the code. Setters and getters are used to access the variables of the class. Since the variables should be private the programmer cannot access them directly so you need an in-between. This also allows for greater control of what goes on since you can add code to make sure the value being provided is valid.

You
This article has been dead for over three months: Start a new discussion instead
Post:
Start New Discussion
View similar articles that have also been tagged: