Thread: Question on Classes

  1. #1
    Master of Puppets rwmarsh's Avatar
    Join Date
    Feb 2006
    Location
    Texas
    Posts
    96

    Question on Classes

    I have a vector that I want to limit access to. I want to only be able to access the vector through a class so that no part of the program can just accidentally go in and change something. Something like this
    Code:
    class My_Class
    {
        public:
            Numbers();
            ~Numbers();
            void Display(int pos1, int pos2);
            void Add(int x);
            void Replace(int x, int pos);
            void Remove(int pos);
            void Clear();
    
        protected:
            vector<int> Numbers;
            vector<int>::iterator iter1;
            vector<int>::iterator iter2;
    };
    
    void Number::Display(int pos1, int pos2)
    {
        for (iter1 = Numbers.begin() + pos1; iter1 <= Numbers.begin() + pos2; ++iter1)
            cout<<*iter1 <<endl;
        return;
    }
    
    void Number::Add(int x)
    {
        Numbers.push_back(x);
        return;
    }
    
    void Replace(int x, int pos)
    {
        Numbers.at(pos) = x;
        return;
    }
    .......
    I am wondering if the vector needs to be protected or private, Or if there is a better way to do this?
    Also, by doing this will the vector remain intact for the entire program or just while the class is in scope?
    Using DEV-C++ Under Windows XP
    +------------------------------+

    "No! Do, or Do Not. There is no Try..."

  2. #2
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Quote Originally Posted by rwmarsh
    I am wondering if the vector needs to be protected or private, Or if there is a better way to do this?
    Also, by doing this will the vector remain intact for the entire program or just while the class is in scope?
    Yep, you have the right idea. Of course, in your example, protected might as well be private because you're not deriving the class. The vector will remain intact as long as the object remains intact (stays in scope). Just like any other variable, as long as the object remains in scope, it's members remain in memory. When it leaves scope, the destructor is called and the data is destroyed.
    Sent from my iPadŽ

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Making it non-public is good design. You should make it private unless you have reason to make it protected, and usually you don't.

    Remember that there will be a separate vector for each instance of your class, so each vector is destroyed automatically when its instance is destroyed.

    Based on your code, there is no reason to make iter1 or iter2 member variables. Just create local iterators in the functions that need them.

    >> iter1 <= Numbers.begin() + pos2
    Don't use <=, use != and have your function follow the same format as containers, which means that the range is [pos1, pos2). If you're not familiar with that notation, it means that it is the range from pos1 to pos2 including pos1 but not including pos2. In other words, it stops after it processes the element just before pos2. You could also have display take a beginning position and a count of the number of elements to display.

  4. #4
    Master of Puppets rwmarsh's Avatar
    Join Date
    Feb 2006
    Location
    Texas
    Posts
    96
    SO based on the class I gave, If I did something like this
    Code:
    int main()
    {
        Number Numbers;
    
        Numbers.Add(3);
        Numbers.Add(2);
        Numbers.Add(7);
        Numbers.Add(6);
    
        Numbers.Display(0, 3);
    
        return 0;
    }
    The vector would stay intact between each call to Numbers and my end result would display
    Code:
    3
    2
    7
    6
    ???
    Using DEV-C++ Under Windows XP
    +------------------------------+

    "No! Do, or Do Not. There is no Try..."

  5. #5
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Yes, that is what would happen based on the code above.

  6. #6
    Master of Puppets rwmarsh's Avatar
    Join Date
    Feb 2006
    Location
    Texas
    Posts
    96
    Great! Thats what I needed to know, Thanx!
    Using DEV-C++ Under Windows XP
    +------------------------------+

    "No! Do, or Do Not. There is no Try..."

  7. #7
    Master of Puppets rwmarsh's Avatar
    Join Date
    Feb 2006
    Location
    Texas
    Posts
    96
    Now I want to expand on the code above. Instead of using a single number I want each element of the vector to hold multiple variables. I made up this code, which works, but I had to use a struct inside the class.
    Code:
    #include <iostream>
    #include <vector>
    #include <string> 
    
    using namespace std; 
    
    class My_Class
    {
        public:
            My_Class();
            ~My_Class();
            void Add(int line_num); 
            void Get(vector<int>::iterator iter2);
    
            vector<int> ref_list; 
    
            struct My_Struct
            {
                string name; 
                string address; 
                string city;
            };
            
            My_Struct Customer_Info;
            
        private: 
            vector<My_Struct> customer_list; 
    }; 
    
     
    int main()
    {
        My_Class Customer;  
        int line_num = 0; 
        int choice;
    
        do
        {
            cout<<endl       
                <<"1 add" <<endl
                <<"2 display" <<endl
                <<"0 exit" <<endl <<endl
                <<"choice : ";
            cin>>choice; cin.ignore();
            cout<<endl;
            switch (choice)
            {
                case 1 :
                    cout<<"name : ";
                    getline(cin, Customer.Customer_Info.name);
                    cout<<"address : ";
                    getline(cin, Customer.Customer_Info.address);
                    cout<<"city : ";
                    getline(cin, Customer.Customer_Info.city);
    
                    Customer.Add(line_num);
                    ++line_num;
                    break;
    
                case 2 :
                    if (Customer.ref_list.size() != 0)
                    {
                        vector<int>::iterator iter;
                        int i = 1;
                        for (iter = Customer.ref_list.begin();
                             iter != Customer.ref_list.end();
                             ++iter)
                        {
                            Customer.Get(iter);
                            cout<<i <<" " <<Customer.Customer_Info.name <<" "
                                << Customer.Customer_Info.address <<" "
                                << Customer.Customer_Info.city <<endl;
                            ++i;
                        }
                        cout<<endl;
                    }
                    else
                        cout<<"no pick ups" <<endl <<endl;
                    break;
    
                case 0 :
                    break;
    
                default :
                    cout<<"invalid choice" <<endl <<endl;
            }
        }
        while (choice != 0); 
    
        return 0;
    } 
    
     
    My_Class::My_Class()
    { 
    } 
    
     
    My_Class::~My_Class()
    { 
    } 
    
     
    void My_Class::Add(int line_num)
    {
        customer_list.push_back(Customer_Info);
        ref_list.push_back(line_num);
        return;
    } 
    
    
    void My_Class::Get(vector<int>::iterator iter2)
    {
        vector<My_Struct>::iterator iter1;
        iter1 = customer_list.begin() + *iter2;
        Customer_Info = *iter1;
        return;
    }
    I know there is a way of doing this without using the struct but when I took it out like and did the class like this
    Code:
    class My_Class
    {
        public:
            My_Class();
            ~My_Class();
            void Add(int line_num); 
            void Get(vector<int>::iterator iter2);
    
            vector<int> ref_list; 
    
            string name; 
            string address; 
            string city;
            
        private: 
            vector<My_Struct> customer_list; 
    };
    all I could get were segmentation errors at run time. I am sure that there is something simple that I am doing, I just can't see it.
    Using DEV-C++ Under Windows XP
    +------------------------------+

    "No! Do, or Do Not. There is no Try..."

  8. #8
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Your second My_Class doesn't look like it will compile, let alone cause a segmentation fault. Where is My_Struct defined that you are using for your customer_list?

    I don't see any problem with defining My_Struct inside My_Class, but if you are asking about the Customer_Info member variable, no it is not necessary.

    One thing I am wondering about is how you use the value in the ref_list vector as an index into the customer_list vector inside the Get function. First, that could be written much more simply as return customer_list[*iter2]; with your Get function returning a My_Struct object. Second, are you sure that the values in the ref_list are all valid indexes into the customer_list? Why even use ref_list if the numbers are just 0, 1, 2 ... i order?

  9. #9
    Master of Puppets rwmarsh's Avatar
    Join Date
    Feb 2006
    Location
    Texas
    Posts
    96
    Your second My_Class doesn't look like it will compile, let alone cause a segmentation fault. Where is My_Struct defined that you are using for your customer_list?
    Sorry, I guess I was half asleep when I did that. Here is the correct code that I have now.
    Code:
    #include <iostream>
    #include <vector>
    #include <string> 
    
    using namespace std; 
    
    class My_Class
    {
        public:
            My_Class();
            ~My_Class();
            void Add(int line_num); 
            void Get(vector<int>::iterator iter2);
    
            vector<int> ref_list; 
    
            string name; 
            string address; 
            string city;
    
        private: 
            vector<My_Class> customer_list; 
    }; 
    
        My_Class Customer;  
     
    int main()
    {
        int line_num = 0; 
        int choice;
    
        do
        {
            cout<<endl       
                <<"1 add" <<endl
                <<"2 display" <<endl
                <<"0 exit" <<endl <<endl
                <<"choice : ";
            cin>>choice; cin.ignore();
            cout<<endl;
            switch (choice)
            {
                case 1 :
                    cout<<"name : ";
                    getline(cin, Customer.name);
                    cout<<"address : ";
                    getline(cin, Customer.address);
                    cout<<"city : ";
                    getline(cin, Customer.city);
    
                    Customer.Add(line_num);
                    line_num++;
                    break;
    
                case 2 :
                    if (Customer.ref_list.size() != 0)
                    {
                        vector<int>::iterator iter;
                        for (iter = Customer.ref_list.begin();
                             iter != Customer.ref_list.end();
                             ++iter)
                        {
                            Customer.Get(iter);
                            cout<<*iter <<" " <<Customer.name <<" "
                                              <<Customer.address <<" "
                                              <<Customer.city <<endl;
                        }
                        cout<<endl;
                    }
                    else
                        cout<<"no customers" <<endl <<endl;
                    break;
    
                case 0 :
                    break;
    
                default :
                    cout<<"invalid choice" <<endl <<endl;
            }
        }
        while (choice != 0); 
    
        return 0;
    } 
    
     
    My_Class::My_Class()
    { 
    } 
    
     
    My_Class::~My_Class()
    { 
    } 
    
     
    void My_Class::Add(int line_num)
    {
        customer_list.push_back(Customer);
        ref_list.push_back(line_num);
        return;
    } 
    
    
    void My_Class::Get(vector<int>::iterator iter)
    {
        Customer = customer_list[*iter];
        return;
    }
    When I go into the loop with the Get function, no matter how many elements I have added with the Add function the program will display the first element and them crash. The compiler does not say anything but I think it is tring to access bad memory for the customer list vector, I just cannot see where it is. Right now, ref_list goes in order ( 0, 1, 2....) so the Get function should get customer_list[0], then [1] then [2]....

    Why even use ref_list if the numbers are just 0, 1, 2 ... i order?
    This is going to be part of a MUCH larger program. It will have the ability to pick certain elements from the vector to display in a summary list based on user input. But I needed a way to reference the elements to do a detail display from the summary. I already have 50+ variables in the customer info struct so I did not want to add more by combining the referece with the others, so I just did another vector. Not sure if that explains very well, but it works....
    Using DEV-C++ Under Windows XP
    +------------------------------+

    "No! Do, or Do Not. There is no Try..."

  10. #10
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Have you learned how to return a value from a function? The My_Class Customer variable should be declared inside main like you had it before, not globally, and your Get function should return a My_Struct object like I said before.

    Start by naming your classes better. My_Class is really a manager class for all the customers, right? So call it CustomerManager or something. Then, you have three strings that is the Customer data that used to be in My_Struct. Put that struct back in but name it something meaningful like CustomerData.

    One current problem with the code, which may or may not be causing the error, is that you are using your global Customer object everywhere. For example, in the Get function you are assigning the value inside the customer_list to Customer, which overwrites the data being held by the Customer already. Go back to having a separate struct for the customer data and learn how to return a value from a function.

  11. #11
    Master of Puppets rwmarsh's Avatar
    Join Date
    Feb 2006
    Location
    Texas
    Posts
    96
    Have you learned how to return a value from a function? The My_Class Customer variable should be declared inside main like you had it before, not globally, and your Get function should return a My_Struct object like I said before.
    Yes, I do know how to return a value, I was just asking if it was proper to define a struct inside a class or not.
    Start by naming your classes better.
    This was just an example that I cam up with real quick. I was not concerned with proper naming as much as I was with learning the language.
    Go back to having a separate struct for the customer data and learn how to return a value from a function.
    Thats what I needed to know; If using the struct in the first place was the best way of doing it.

    Im sorry if I did not explain that better earlier.
    Using DEV-C++ Under Windows XP
    +------------------------------+

    "No! Do, or Do Not. There is no Try..."

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Classes question...
    By Raigne in forum C++ Programming
    Replies: 24
    Last Post: 09-12-2006, 01:46 AM
  2. Replies: 2
    Last Post: 07-28-2006, 02:59 PM
  3. Simple Question about Classes
    By Loctan in forum C++ Programming
    Replies: 5
    Last Post: 06-26-2006, 02:40 AM
  4. Classes and Win32 API, and another Question
    By philvaira in forum Windows Programming
    Replies: 10
    Last Post: 04-10-2004, 07:21 PM
  5. Newbie question about the Private type in classes
    By Ryeguy457 in forum C++ Programming
    Replies: 1
    Last Post: 09-07-2002, 10:17 PM