Problems defining classes

This is a discussion on Problems defining classes within the C++ Programming forums, part of the General Programming Boards category; So if I understood correctly it would be something like: Code: class Owner { private: ... vector<vehicle*> public ... } ...

  1. #31
    Registered User
    Join Date
    Oct 2007
    Posts
    37
    So if I understood correctly it would be something like:

    Code:
    class Owner 
    { 
    
    private:
    ...
    vector<vehicle*> 
    
    public
    ...
    }
    
    class Vehicle
    
     {
        public:
            ...
    
        private:
            ...
        vector<owner*>
    
    }
    
    class cra
    {
    private:
    ...
    vector<vehicle*> 
    vector<owner*>
    
    public:
    ...
    }
    Is this right?

  2. #32
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Not how I would do it.

    If you have some form of "association" class (cra in your case), it should be the only place where you connect the owner and the vehicle.

    You almost certainly don't need a "vector<owner *>" in your vehicle class - that would cover the case where you have multiple owners of a vehicle, which I don't even think is possible [at least not in the UK, you have a "registered keeper", which is the "owner", even if the actual owner is for example a company].

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #33
    Registered User
    Join Date
    Jan 2005
    Posts
    7,328
    That is one way to do it, yes. You just have to take extra care to clean up all pointers to things that are deleted. In that scenario the cra class would manage the lifetimes of the vehicle and owner objects.

    My wife and I jointly own one of our cars, and it is certainly allowed for use to have separate cars in our own names individually, so multiple owners might be allowed. Of course, it all depends on the problem space whether that is a requirement or not.

  4. #34
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Daved View Post
    My wife and I jointly own one of our cars, and it is certainly allowed for use to have separate cars in our own names individually, so multiple owners might be allowed. Of course, it all depends on the problem space whether that is a requirement or not.
    Just goes to show that what applies in one country doesn't necessarily apply in another country.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #35
    Registered User
    Join Date
    Oct 2007
    Posts
    37

    ...


    Not how I would do it.

    If you have some form of "association" class (cra in your case), it should be the only place where you connect the owner and the vehicle.

    You almost certainly don't need a "vector<owner *>" in your vehicle class - that would cover the case where you have multiple owners of a vehicle, which I don't even think is possible [at least not in the UK, you have a "registered keeper", which is the "owner", even if the actual owner is for example a company].
    Well,the problem explicitaly says that a car just have one owner...So,regarding to what you've said you could have the association defined by vectors like this:

    Code:
    class Owner { ... }
    
    class Vehicle{ ... }
    
    class cra
    {
    private:
    ...
    vector < pair <vehicle*,owner* > > ownerv;
    
    
    public:
    ...
    }
    Or by maps like this:

    Code:
    class Owner { ... }
    
    class Vehicle{ ... }
    
    class cra
    {
    private:
    ...
    
    map<string, Vehicle> vehicles;
    map<long, Owner> owners; 
    multimap<long, string> OwnedVehicleMap;
    
    public:
    ...
    }
    Does this look ok?And thanks for all the help!
    Last edited by esmeco; 10-13-2007 at 09:08 AM.

  6. #36
    Registered User
    Join Date
    Oct 2007
    Posts
    37
    Also, if I wanted to,after storing the vehicles' and owners' information, list the owners' information and their owned vehicles how would I do it in terms of coding?

  7. #37
    Registered User
    Join Date
    Oct 2007
    Posts
    37

    ...

    Just one more question that has been aching my head: why would I want to use maps instead of vectors in this case?What are the differences?

  8. #38
    Registered User
    Join Date
    Jan 2005
    Posts
    7,328
    >> the problem explicitaly says that a car just have one owner.
    I guess I missed that. Remember my comments were based on the assumption that a car can have multiple owners.


    About your entire design. First understand the difference between referencing and management of an object (normally I would say ownership but because the problem includes something called an "owner" I don't want to use that term). A reference is a way for one object to refer to another. This can be a pointer. It can also be a key. For example, if the vehicle stored the ownerId of its owner, then it would be referencing the owner.

    Management in this case means keeping track of the lifetime of the object in the program. It means having control of the actual instance and being able to create or destroy instances. Any object can only be managed by one other object. For example, if you have an owner contain a vector<Vehicle>, then it has a vector of objects (not pointers). That means it is containing and managing the actual Vehicle objects. If the Owner object is destroyed it's vehicle is destroyed. If it contained a vector<string> that was a list of the licenses of the owned vehicles, then it would be referencing them instead of "managing" them.

    So if you understand that difference, here are the things you need to do in this program.
    1. You need to manage all the Owner objects in the application. Something has to control when an Owner instance is created and when they are destroyed.
    2. You need to manage the Vehicle objects somehow. You can do this by having each owner hold its own vehicles, or have a container that holds all vehicles in the application.
    3. You need to be able to find the vehicle from the owner. You need this because you want to "list the owners' information and their owned vehicles". This means two things. One is that the Vehicle should not manage the Owner, it can only reference it. Since multiple Vehicles can be owned by the same Owner, and an object can only be "managed" by one other object, it won't work to have Vehicles manage Owners. The other thing it means is that Owners need to reference or manage their vehicles. You have to quickly and easily get from an Owner to its Vehicles.
    4. You probably need to be able to find an owner from a vehicle. In that case, the Vehicle needs to reference the Owner, because as we just said the Vehicle cannot manage the Owner.


    So, for #1, who should manage the Owners? It can't be the Vehicles, and the Owners can't manage themselves, so I'd say the autoreg class should manage the Owners. To do this there are several options, which is best depends on other decisions:
    1. You can have a simple list (e.g. vector<Owner>). But assuming you need to be able to have the Vehicle reference the Owner (#4 above), that might be difficult. A pointer wouldn't work because a pointer doesn't always remain valid when an object is in a vector. An index might work, but then an Owner should never move around or get deleted from the vector.
    2. You can have a list of dynamically allocated Owners (e.g. vector<Owner*>). This has the benefit of ensuring the pointers are never changed by the vector. The Vehicle can reference the Owner via a pointer and be confident that as long as the Owner is valid the pointer will point to it. The disadvantage is that you have to handle the memory management yourself and cleanup the Owners when they are removed.
    3. You can have a map of Owners with their unique ids as the key (e.g. map<long, Owner>). One benefit here is that you don't have to do memory management. Another benefit is that the Vehicle can reference its Owner by keeping track of its ownerId. To look up the Owner, it just looks up the OwnerId in the map. The Id will never point to dangling memory, if the Owner is deleted then no entry will exist in the map. This means its safer. You can implement this solution with a vector as well. A simple vector<Owner> could work if the ownerId was sequential and starting at 0 (or 1) like an index. You could also sort the vector based on the OwnerId for fast access, and then look up via binary_search. Finally, if your application doesn't care about speed, you can just use a vector<Owner> and lookup the ownerId with a linear search.


    If you don't need #4, then use a vector<Owner> inside the autoreg class. Otherwise, use whichever option above is most comfortable for you. I'd pick option C because it scales nicely and doesn't require memory management.

    Now, what about for #2? Who manages the Vehicles, and how? As I said earlier, you could let the autoreg class manage the Vehicles, or you could let the Owner manage the Vehicles it owns.
    1. If you let the autoreg class manage the Vehicles, it would mean that you would need a reference from the Owner to its Vehicles (for #3). The options here are similar to the options for referencing the Owner from the Vehicle. The first is a vector<Vehicle>. Negative is that referencing via pointer is bad, and referencing via index only works if you are strict about moving and/or deleting the Vehicles in the vector.
    2. The second option is to contain a vector<Vehicle*> in the autoreg class. As above, the benefit is that an Owner can reference its vehicles with a vector<Owner*> of its own without worrying too much about the pointers changing randomly. The drawback is that you have to do the memory management and messing that up is more dangerous.
    3. The third option is a map in the autoreg class. Again, a map<string, Vehicle> would work, since it would map the Vehicle based on its unique license. You could also use a vector<Vehicle> sorted by license, or you could use a vector<Vehicle> with a linear search. The Owner would then contain a vector<string> which is a list of the licenses of all Vehicles owned by that Owner.
    4. You don't have to have the autoreg class manage the Vehicles. You can have each Owner manager the Vehicles it owns. The simplest way to do this is a vector<Vehicle> inside each Owner. The downside is that you don't have easy access to all the Vehicles. If you need to print out each Vehicle or look up a Vehicle by its license, then you need to search through all the Owners to find it. If you manage Vehicles in the autoreg class then they are all stored right there and it is not as difficult.


    So for this problem, I would use either option C or D. Use D only if you don't need much access to the Vehicles and they are only there as part of an Owner's data. I would use option C if you want to be able to access Vehicle data separately from the Owner.


    Finally, what about #3 and #4, I already mentioned ideas above on how to do those, but you have the option of storing the references in the objects themselves or in the autoreg class. My earlier example used the autoreg class to do that.
    1. For option A it depends. As I said getting the references to work is difficult for this option.
    2. For option B, have the Owner store a vector<Vehicle*> (#3) and have the Vehicle store an Owner* (#4). Or have the autoreg class hold a multimap<Owner*, Vehicle*> for #3 and a map<Vehicle*, Owner*> for #4.
    3. For option C, you can have the Owner store a vector<string> to hold the Vehicle licenses for #3 and have the Vehicle store an ownerId for its Owner to handle #4. Or you can have the autoreg class contain a multimap<long, string> to map the ownerId to Vehicle license for #3 and a map<string, long> to map the Vehicle license to its Owner's Id for #4.
    4. For option D, you don't need to have the Owner reference it's Vehicles, since it manages them, so #3 is already solved. For #4 you can use many techniques, but a simple Owner* in the Vehicle class or a map<Vehicle*, Owner*> in the autoreg class would work.


    Whether you store the references in the Owner and Vehicle classes or in the autoreg class is up to you. The suggestion I had earlier was option C with the multimap/map in the autoreg class, but I think Option C with the objects containing the references is just as good.


    There are still many more ways to do this than the above. For example, you might want to have a class other than autoreg manage the Owners and/or Vehicles. Hopefully this gives you an idea of different things you need to be concerned about, and ways you can implement solutions to those things. Identify who will "manage" the Owners and the Vehicles, and how each will be able to reference each other.
    Last edited by Daved; 10-15-2007 at 01:17 PM.

  9. #39
    Registered User
    Join Date
    Oct 2007
    Posts
    37

    ...

    I've read all this and I must say it will give me a giant leap ahead on my work!Very very insightful,thank you so much for all the work!Later tonight,I'll post my code so that you,if possible,give me some help and suggestions!Thanks again!

  10. #40
    Registered User
    Join Date
    Oct 2007
    Posts
    37

    ..

    This's my actual code...I'm having a bit of difficulty about some coding: in class autoreg defined de <map> as public...Should I put them has private instead?Another thing,once I have in autoreg a method in_ov(...) whose arguments are the objects of vehicle and owner(since that way it's easier to be,instead of sending all the attribute parameters ' of the classes like name,address,etc.),I have created a autoreg.cpp so that I can call that function from main .
    In main I want to call that function,since user introduced data before,I would like to send them to the method in autoreg.cpp so that it could keep the data in the variables created created within the classes vehicle and owner and,later on,in that same function,create pair between the vehicles and owners association...I just don't have a clue how will I send all these data on the function since what I have there are the objects of both classes(owner and vehicle).
    Could someone please help me out a bit with my code?
    Just one last question: Is it necessary for constructors to exist in clas owner and vehicle given that who will manage that is the autoreg class throught their own add,clear methods?



    Code:
    #include<iostream>
    #include <string>
    
    using namespace std;
    
    class vehicle
    {
    private:
    	string license;
    	string brand;
    	string color;
    	string model;
    	long cil;
    	long ccv;
    	long nowner;
    	
    
    public:
    
    	vehicle();
    	vehicle(string str_ license,string str_brand,string str_color,string str_model,long n_cil,long n_ccv,long n_nowner);
    	string get license(void) const;
    	void set license(string str_ license);
    	string getbrand(void) const;
    	void setbrand(string str_brand);
    	string getcolor(void) const;
    	void setcolor(string str_color);
    	string getmodel(void) const;
    	void setmodel(string str_model);
    	long getcil(void) const;
    	void setcil(unsigned long n_cil);
    	long getccv(void) const;
    	void setccv(long n_ccv);
    	long getnowner(void) const;
    	void setnowner(long n_nowner);
        
    };
    Code:
    #include <iostream>
    #include <string>
    using namespace std;
    
    class owner
    {
    private:
    	string name;
    	long id;
    	string address;
    	long phone;
    	
    public:
    	owner();
    	owner(string str_name,long sid,string str_address,long sphone);
    	string getname(void) const;
    	void setname(string str_name);
    	string getaddress(void) const;
    	void setaddress(string str_address);
    	long getid(void) const;
    	void setid(long sid);
    	long getphone(void) const;
    	void setphone(long sphone);
    
    	
    };

    Code:
    #include <iostream>
    #include <map>
    #include <string>
    #include "vehicle.h"
    #include "owner.h"
    
    using namespace std;
    
    class autoreg
    {
    
    public:
    	
    	map<string,vehicle>;
    	map<long, owner>;
    	multimap<long, string>; 
    	map<string, long>;
    
    	void in_ov(vehicle v,owner p);
    	void er_vehicle(vehicle v);
    	void er_ov(vehicle v,owner p);
    	search(vehicle v,owner p);
    
    }

    autoreg.cpp


    Code:
    #include "autoreg.h"
    using namespace std;
    
    cra::void in_ov(vehicle v,owner p)
    {
    
        
     }
    
    cra::er_vehicle(vehicle v);
     {
    
    	 
     }
    
     cra::er_ov(vehicle v,owner p);
     {
    
     }
    
    cra::search(vehicle v,owner p);
    {
    }
    Code:
    #include <stdlib.h>
    #include <iostream>
    #include <string>
    #include "autoreg.h"
    #include "vehicle.h"
    #include "owner.h"
    
    
    void main()
    {
    
      char input;
      string name,add,brand,model,color,lic;
      long id,ph,cil,ccv,nrowner;
      vehicle v;
      owner p;
      cra r;
    
      cout << "AutoREG" "\n"<< endl;
      while( 1 )
      {
    	  cout << "Add client and vehicle(a):""\n"<< endl; 
    	  cout << "Remove owner(r):""\n"<< endl;
    	  cout <<	"Remove vehicle(x):""\n"<<endl ; 
    	  cout <<	"Refresh owners and vehicles(z):""\n"<<endl ;
    	  cout <<	"List vehicles(v):" "\n"<<endl;
    	  cout <<	"List owners(o):""\n"<< endl; 
    	  cout <<	"Exit(e): ""\n"<< endl;
          cin >> input;
    
        switch( input )
        {
        case 'a':
          {    
            cout <<"Name: " <<endl;
            cin>>name;
            cout<<"ID: "<<endl;
            cin >>id;
            cout<<"Address: "<<endl;
             cin>>add;
            cout<<"Phone: "<<endl;
            cin >>ph;
            cout <<"Brand: "<<endl;
            cin >>brand;
            cout << "License: "<<endl;
            cin >>lic;
            cout << "Color: "<<endl;
            cin >>colorr;
            cout << "Model: "<<endl;
            cin >>model;
            cout << "Cil: "<<endl;
            cin >>cil;
           cout<<"ccv: "<<endl;
           cin >>pot;
           cout<<"Nr de old owners: "<<endl;
            cin >>nrowner;
            r.in_ov(v,p);
    
    	  }
          continue;
    	case 's':
    		exit(0);
    	default:
          cout << "Error: Input valid char " << input << '\n';
          break;
     }
      }
    
     
    }
    [B]Owner.cppB]

    Code:
    #include <iostream>
    #include <string>
    #include "owner.h"
    
    owner::owner(string str_name,long sid,string str_address,long sphone)
    {
                    name = str_name;
    	id=sid;
    	phone=sphone;
    	adress = str_adress;
    }
    string owner::getname() const
    {
      return name;
    };
    
    void owner::setname(string str_name)
    {
    	name=str_name;
    };
    
    string owner::getadress() const
    {
    	return adress;
    };
    
    void owner::setadress(string str_adress)
    {
    	adress=str_adress;	
    };
    
    long owner::getid() const
    {
    	return id;
    };
    
    void owner::setid(long sbi)
    {
    	id=sid;
    };
    
    long owner::getphone() const
    {
    	return phone;
    };
    
    void owner::setphone(long sphone)
    {
    	phone=sphone;
    };
    Code:
    #include<iostream>
    #include<string>
    #include "vehicle.h"
    
    vehicle::vehicle(string str_ license,string str_brand,string str_color,string str_model,long n_cil,long n_ccv,long n_nowner)
    
    {
    license=str_license;
    brand=str_brand;
    color=str_color;
    model=str_model;
    cil=n_cil;
    ccv=n_ccv;
    nowner=n_nowner;
    
    }

    PS:Feel free to give suggestions or point out if there's code which isn't necessary,or even suggest corrections!

  11. #41
    Registered User
    Join Date
    Oct 2007
    Posts
    37

    ...

    Could anyone help me on this?

  12. #42
    Registered User
    Join Date
    Jan 2005
    Posts
    7,328
    >> Should I put them has private instead?
    Yes. Keep them private and provide public access to the data they hold. I would have functions like GetVehicleOwner that looks up a vehicle's owner by using the maps.

    >> I just don't have a clue how will I send all these data on the function
    I would create an owner object and a vehicle object with the values input by the user, then pass those to your functions:
    Code:
    owner new_owner(name, id, add, ph);
    vehicle new_vehicle(lic, brand, colorr, model, cil, pot, nowner);
    r.in_ov(new_vehicle, new_owner);
    In reality, I might separate the add owner and add vehicle functions in the cra class and add them separately. What if the user wants to add a new vehicle to an existing owner?

    >> Is it necessary for constructors to exist in clas owner and vehicle given that who will manage that is the autoreg class throught their own add,clear methods?
    Not necessary, but you should still do it. The vehicle and owner classes shouldn't rely on auto_reg, they should be valid classes in their own right. It is also better to construct them with all their data from the beginning rather than create one and call set for each data item.

    >> Feel free to give suggestions
    I would add header include guards to your header files. This is important for proper compilation.
    I would use int main instead of void main, void main is not proper C++.
    I would give longer, more descriptive variable names to make the code easier to read and follow.
    I would use an initializer list in your constructors, although you might want to wait until your other coding is finished and working before worrying about this since how you have it now works too.

  13. #43
    Registered User
    Join Date
    Oct 2007
    Posts
    37

    ..

    Thank you very much for the explanation and help!Here I've changed a bit the main function and class autoreg taking into account what you've said.
    When compiling I get 2 errors of linkage saying the following:

    autoreg.obj : error LNK2019: unresolved external symbol "public: __thiscall..."

    Also,I have a warning that says: "warning C4715: 'autoreg::getownersvehicles' : not all control paths return a value

    Do you have any idea,based on the code I've provided what may be causing this?

    Code:
    class autoreg
    {
    
    private:
    
    	
    	typedef map<string,vehicle> vehicles;
    	typedef map<long, owner> owners;
    	typedef multimap<long, string> ovmap; 
    	typedef map<string, long> ids;
    
    public:
                    string getownersvehicles() const;
    	void in_ov(vehicle v,owner p);
    	void er_vehicle(vehicle v);
    	void er_ov(vehicle v,owner p);
    	search(vehicle v,owner p);
    
    }

    Code:
    void autoreg::in_ov(vehicle v,owner p)
    {  
       vehicles vh;
       ovmap ovm;
       owners odata;
       long id=p.getid();
       string lic=vh.getlicense();  
    
       odata.insert(make_pair(id,p));  
       vh.insert(make_pair(lic,v));   
       ovm.insert(make_pair(id,lic));
    }
    
    
    string autoreg::getownersvehicles() const
    {
     owner p;
     long id=p.getid();
     ovmap ovm;
      vehicles vh;
      owners odata;
    
    pair<ovmap::const_iterator, ovmap::const_iterator> list_vehicles
          = ovm.equal_range(id);
    
    owner& owns = data[id];
    cout << owns.getname() << " has:\n";
    
    while (list_vehicles.first != list_vehicles.second)
    {
        string license = list_vehicles.first->second;
        vehicle& current_car = vh[license];
    
        return current_car.getbrand();
        return current_car.getmodel();
    
        ++list_vehicles.first;
    }
    }
    Code:
    int main
    {
    ...
    owner new_owner(name, id, add, ph);
    vehicle new_vehicle(lic, brand, colorr, model, cil, pot, nowner);
    r.in_ov(new_vehicle, new_owner);
    ...
    
    case 'n':
          {   
    		  autoreg auto;
    		  auto.getownersvehicles();
    		
      }
    ...
    Last edited by esmeco; 10-19-2007 at 08:21 PM.

  14. #44
    Registered User
    Join Date
    Jan 2005
    Posts
    7,328
    >> autoreg.obj : error LNK2019: unresolved external symbol "public: __thiscall..."
    The part of the error message that was snipped off is important. What's the rest of the error message?

    >> warning C4715: 'autoreg::getownersvehicles' : not all control paths return a value
    This seems pretty self-explanatory. The function autoreg::getownersvehicles promises to return something, but there are ways the code can go that don't return anything. Of course, you are trying to return a string, but what you seem to want to do is return all vehicles owned by that owner, is that right? If so, you want to return a list of vehicles (maybe a vector<vehicle>) so that you can return all the vehicles and display there brand, model, etc.

    As to your code, hopefully you've realized this by now but your member variables for the autoreg class aren't member variables. You created typedefs, then created local variables in the functions. That's not good, because the local maps you create in the function go out of scope and are destroyed when the function ends, so your autoreg class will never remember any data you give it. If you want typedefs, you need to also add member variables to the autoreg class, or if you didn't mean to do the typedef (or didn't know what you were doing), then remove the typedef word from those private variables.

  15. #45
    Registered User
    Join Date
    Oct 2007
    Posts
    37

    ...

    Thank you for the tips!
    It does work now...But,just one question,why do they get out of scope?

Page 3 of 4 FirstFirst 1234 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. College Classes
    By nubby in forum C Programming
    Replies: 2
    Last Post: 10-07-2007, 12:32 AM
  2. Inheritance, overriding, problems
    By CodeMonkey in forum C++ Programming
    Replies: 8
    Last Post: 01-04-2007, 12:26 AM
  3. classes, inheritance and include problems
    By baniakjr in forum C++ Programming
    Replies: 6
    Last Post: 12-12-2006, 12:45 PM
  4. C++ Classes: Use, Misuse...Confusion.
    By Snorpy_Py in forum C++ Programming
    Replies: 4
    Last Post: 10-23-2006, 01:46 AM
  5. Sharing a variable between classes of different .CPP files
    By divingcrab in forum C++ Programming
    Replies: 5
    Last Post: 07-07-2002, 02:57 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21