-
iterator to pointer conversion
Need some help with STL containers.
Say you have an STL list of objects of class X:
std::list<X> Xlist;
And you have a const_iterator to the first element of this container:
std::list<X>::const_iterator iter = Xlist.begin();
Now since X inherits from a base class (BaseX), you would like to create another STL list: one that contains base class pointers for all objects in Xlist:
std::list<BaseX*> BaseXlist;
What is the safest machine-independent way to do this? I assume you have to obtain access to the base-class pointer via some dereferencing and convert it via pointer arithmetic. I have developed a function that returns a base class pointer (given an iterator to a derived class) but was told this is not safe. It works though.
Here is the function definition:
BaseX* anyClass::getBasePointer(std::list<X>::const_iterator iter)
{
void* pAction = &iter;
int** ppActionInt = static_cast<int**>(pAction);
int* pActionInt = *ppActionInt;
++(++pActionInt);
pAction = pActionInt;
return static_cast<BaseX*>(pAction);
}
Any help would be appreciated !!
-
You technique is indeed inherently dangerous and error prone. The short answer is that you can't convert pointers safely, but there are a few general pricnicnples: first, to obtain the address of an element through an iterator, use &*it;
secondly, you need to use a contiguous container such as vector, certainly not list. Finally, I'm not sure I understand the relationship between the base class and its derived classes. Why would you need two containers in the first place? Simply store the derived objects and use their virtual functions to achieve polymorphism.
Danny Kalev
-
The reason for the second container is as follows:
I am required to introduce a new class (I'll call this Class Y). Class Y will inherit from BaseX as well.
I need to create a "super list" that would contain elements of class X and those of class Y. The only way I could do that was to introduce a base class that X and Y inherit from. Then I could make an STL list of base pointers and achieve polymorphism by iterating thru my super list invoking the pure virtual functions.
Is there an easier way to achieve this?
To summarize, this is what I started with:
std::list<X> Xlist;
X objects have a validate() and apply() function.
A new class then came into existence per requirements.
This new class also need to implement a validate() and apply() function.
I therefore created a base class (BaseX is a bad name at this time, a more appropriate name was BaseXY) with two pure virtual functions, validate() and apply().
Class X and (the new) Class Y both inherit from BaseXY and are required to implement their own validate() and apply() functions.
My ultimate goal was to create an STL list of X and Y objects given two separate containers (an STL list of X objects and an STL list of Y objects). Sort of like merging a list but not really. The elements in the lists are time-ordered and this time-ordering must be preserved in the process of merging the two lists.
The only way to achieve this was thru base class pointers (BaseXY is an abstract base class).
I therefore invented the function to convert an interator to an X object into a BaseXY* that I could insert into:
std::list<BaseXY*> baseXYlist;
Hope that's a little clearer. Thanks again.
-
I think your design is overkill. You obviously want a heterogeneous container, something quite common in C++. There are several ways to accomplish this, but they all are much simpler than it seems: you use a single container of pointers to base, and store in it pointers to actual objects that may be of type derived1, derived2 and so on. In good OO design, you never inquire an object for its dynamic type, i.e., is it really BaseXY or is it X or Y? You simply assume that all these classes share a common interface of virtual functions that do the right thing. In most cases, this will suffice. If however for some reason you truly need to extract the dynamic type of the object to which the pointer is bound, use RTTI. That's exactly what RTTI is for. You can read more about heterogeneous containers and RTTI here:
http://www.devx.com/cplus/10MinuteSolution/28347 //heter. are discussed at the end
http://www.devx.com/getHelpOn/Article/10202 //RTTI
Danny Kalev
-
I tried using the std::tr1::share_ptr but my compiler doesn't like it. I #included <memory>. I have MS Visual 7.1.
-
It doesn't like it because shared_ptr isn't in C++ yet, at least not in ISO C++. Expect to find it in a couple of years... Seriously, you can download it from Boost (see the instructions on the Solution) or simply use raw pointers as elements of the vector, as shown in the first Solution about heterogeneous containers: http://www.devx.com/cplus/10MinuteSolution/29757
Danny Kalev
Similar Threads
-
Replies: 3
Last Post: 05-19-2005, 05:19 AM
-
By Sangeetha in forum .NET
Replies: 1
Last Post: 04-18-2002, 07:36 AM
-
By Sean Woods in forum VB Classic
Replies: 4
Last Post: 12-06-2001, 04:48 PM
-
By Sean Woods in forum VB Classic
Replies: 0
Last Post: 12-06-2001, 03:22 PM
-
By Ivo Ivanov in forum Web
Replies: 0
Last Post: 05-09-2001, 06:08 PM
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
Forum Rules
|
Top DevX Stories
Easy Web Services with SQL Server 2005 HTTP Endpoints
JavaOne 2005: Java Platform Roadmap Focuses on Ease of Development, Sun Focuses on the "Free" in F.O.S.S.
Wed Yourself to UML with the Power of Associations
Microsoft to Add AJAX Capabilities to ASP.NET
IBM's Cloudscape Versus MySQL
|
Bookmarks