![]() |
| | #1 |
| Registered User Join Date: Oct 2009
Posts: 38
| Virtual functions Code: string Hallway::toString() {
ostringstream result;
result<<"The hallway consists of "<<getRoomVec().size()<<" rooms."<<endl;
result<<"---------------------------------------------"<<endl;
for(int i=0;i<getRoomVec().size();i++) {
result<<getRoomVec().at(i).toString()<<endl;
}
result<<"---------------------------------------------"<<endl;
return result.str();
}
Code: string Bedroom::toString() {
ostringstream result;
result<<"The bedroom consists of: "<<endl;
result<<"---------------------------------------------"<<endl;
for(int i=0;i < getItemVec().size();i++) {
result<<getItemVec().at(i).toString()<<endl;
}
result<<"---------------------------------------------"<<endl;
if(areLightsOn())
result<<"The bedroom's lights are on."<<endl;
else
result<<"The bedroom's lights are off."<<endl;
result<<"The remaining length to the bedroom is "<<getAvailableL()<<"."<<endl;
result<<"The remaining width to the bedroom is "<<getAvailableW()<<"."<<endl;
return result.str();
}
Code: string Bathroom::toString() {
ostringstream result;
result<<"The bathroom consists of: "<<endl;
result<<"---------------------------------------------"<<endl;
if(getShowerVec().size() > 0) {
for(int i=0;i<getShowerVec().size();i++)
result<<getShowerVec().at(i).toString()<<endl;
}
if(getStallVec().size() > 0) {
for(int i=0;i<getStallVec().size();i++)
result<<getStallVec().at(i).toString()<<endl;
}
if(getSinkVec().size() > 0) {
for(int i=0;i<getSinkVec().size();i++)
result<<getSinkVec().at(i).toString()<<endl;
}
if(getMirrorVec().size() > 0) {
for(int i=0;i<getMirrorVec().size();i++)
result<<getMirrorVec().at(i).toString()<<endl;
}
result<<"---------------------------------------------"<<endl;
if(areLightsOn())
result<<"The bathroom's lights are on."<<endl;
else
result<<"The bathroom's lights are off."<<endl;
result<<"The remaining length to the bathroom is "<<getAvailableL()<<"."<<endl;
result<<"The remaining width to the bathroom is "<<getAvailableW()<<"."<<endl;
return result.str();
}
Code: string Room::toString() {
string nothing;
return nothing;
}
Code: int main() {
Bathroom room;
Shower one;
Shower two;
Stall three;
Stall four;
Stall five;
Mirror six;
Sink seven;
room.addShower(one);
room.addShower(two);
room.addStall(three);
room.addStall(four);
room.addStall(five);
room.addMirror(six);
room.addSink(seven);
Hallway hall;
hall.addBathroom(room);
cout<<hall.toString();
return 0;
}
|
| SterlingM is offline | |
| | #2 |
| Registered User Join Date: Sep 2004 Location: California
Posts: 2,845
| Code: I'm assuming it's because the Hallway is a vector of Room's and not Bathroom's or Bedroom's.
__________________ bit∙hub [bit-huhb] n. A source and destination for information. |
| bithub is offline | |
| | #3 | |
| Mysterious C++ User Join Date: Oct 2007
Posts: 14,099
| Polymorphism only works on pointers or references. Furthermore, when you add a non-pointer to an object, you slice it. Meaning that everything that is not a Room is lost in the conversion to a Room. So in effect: you need to store pointers allocated with new or some such. You can use smart pointers to avoid memory management.
__________________ Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System I dedicated my life to helping others. This is only a small sample of what they said: "Thanks Elysia. You're a programming master! How the hell do you know every thing?" Quoted... at least once. Quote:
| |
| Elysia is offline | |
| | #4 |
| Registered User Join Date: Jan 2005
Posts: 7,137
| The problem appears to be that your Hallway vector holds Room objects, not pointers. Since it holds Room objects, every time you add a Bathroom or Bedroom to the hallway, you slice off the derived-ness of the class and only the base class data is saved. Dynamic polymorphism, which is what you're correctly trying to use, only works on pointers or references. You can't store references in vectors or arrays, so you have to store pointers. Make Hallway store a vector<Room*> instead. Doing this brings up some other interesting challenges. The most important is, who "owns" the Rooms? It probably doesn't make sense for a Hallway to own the rooms it is connected to, so you'll have to identify something else that keeps the master pointer to each room and deletes it when it is all done. There are more advanced tools to help with this, including shared_ptr. If you can use that, I'd recommend it, but often that is not allowed for assignments since you'd have to get another library like boost. If you can't, then you just have to pay extra attention to who maintains the pointer and when it gets deleted. |
| Daved is offline | |
| | #5 | |
| Mysterious C++ User Join Date: Oct 2007
Posts: 14,099
| As a side note, shared_ptr is also available in TR1: std::tr1::shared_ptr and in C++0x: std::shared_ptr.
__________________ Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System I dedicated my life to helping others. This is only a small sample of what they said: "Thanks Elysia. You're a programming master! How the hell do you know every thing?" Quoted... at least once. Quote:
| |
| Elysia is offline | |
| | #6 |
| Registered User Join Date: Oct 2009
Posts: 38
| Okay I got it working how I wanted it. Another question though, is there any way I could check whether a Room was a Bathroom or Bedroom? Mainly to have a Hallway toString() looks something like this Room 1 is a //Bedroom or Bathroom It consists of ... Then continue along |
| SterlingM is offline | |
| | #7 |
| Registered User Join Date: Jan 2005
Posts: 7,137
| That should not be part of the Hallway code, that should be part of the Bedroom or Bathroom toString methods (or part of the Room toString method if you wanted to get a little fancier). If you don't want that part of the toString() for Bedroom and Bathroom, you can have the Hallway do something like this: Code: cout << "Room " << room_index+1 << " is a " << rooms[room_index]->getRoomTypeName() << '\n'; // ... Last edited by Daved; 11-02-2009 at 07:25 PM. |
| Daved is offline | |
| | #8 | |
| Registered User Join Date: Oct 2006
Posts: 263
| Quote:
Code: Room *room = new Room;
if (dynamic_cast<Bathroom*>(room))
{
std::cout << "room is a Bathroom." << std::endl;
}
else if (dynamic_cast<Bedroom*>(room))
{
std::cout << "room is a Bedroom." << std::endl;
}
else
{
std::cout << "room is neither." << std::endl;
}
| |
| Elkvis is offline | |
| | #9 |
| Registered User Join Date: Oct 2009
Posts: 38
| Yeah I had planned on putting it into Room's toString(), but how can a Room pointer check what type of Room it is? Is there a function for situations like this? |
| SterlingM is offline | |
| | #10 |
| Registered User Join Date: Oct 2009
Posts: 38
| Ah okay, the above code got posted before I posted. |
| SterlingM is offline | |
| | #11 |
| Registered User Join Date: Nov 2009
Posts: 2
| ---"Polymorphism only works on pointers or references." This is the answer. For more, please refer to STL allocator. |
| YuJunheng is offline | |
| | #12 | |
| Mysterious C++ User Join Date: Oct 2007
Posts: 14,099
| You should not rely on deducing the type of the pointer or object. You should rely on the proper functions being called by the compiler. Derive multiple classes from Room, each with your different type of room and overload your virtual function for each of them. When called, the proper function in the proper class will be called due to polymorphism. You do not need to know the type, unlike Java.
__________________ Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System I dedicated my life to helping others. This is only a small sample of what they said: "Thanks Elysia. You're a programming master! How the hell do you know every thing?" Quoted... at least once. Quote:
| |
| Elysia is offline | |
| | #13 |
| Registered User Join Date: Jan 2005
Posts: 7,137
| >> you can use dynamic_cast You can, but that's a bad idea here and a bad habit to get into. Don't do it. >> how can a Room pointer check what type of Room it is? It doesn't have to. If you use the Room's toString() method, you could do something like this: Code: cout << "Room " << room_id << " is a " << getRoomTypeName() << '\n'; If you find yourself trying to identify which derived type your Room pointer points to, you need to rethink what you're doing. Usually, whatever information you are trying to get (in this case, the type of room as a string) can be moved into a separate virtual function that can then be called on the Room pointer. That way you don't need to know what derived class it is, the virtual function will handle that for you. Does that make sense? |
| Daved is offline | |
![]() |
| Thread Tools | |
| Display Modes | |
|
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| i need a good example of virtual functions | Anddos | C++ Programming | 10 | 02-15-2006 11:48 AM |
| Virtual Functions | guda | C++ Programming | 3 | 11-16-2004 04:13 PM |
| Thread creation on virtual functions | gustavosserra | C++ Programming | 13 | 10-14-2004 08:03 AM |
| recursive virtual functions | ygfperson | C++ Programming | 0 | 05-25-2003 08:00 PM |
| Exporting Object Hierarchies from a DLL | andy668 | C++ Programming | 0 | 10-20-2001 01:26 PM |