Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game. |
Notices |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
|
|
01-14-2007, 05:17 AM
|
#1
|
Senior Member
Registered: Sep 2004
Location: Sweden
Distribution: Ubuntu, Debian
Posts: 1,109
Rep:
|
Two return types
Hi,
Simple question: if I have a method in a class which will return either type A or type B, how should I do?
I have a list of objects, the objects can be of two types. So when I call at(int) it can return either a pointer to object of type A or a pointer to an object of type B.
EDIT:
To extend it a little bit, is there a way of managing a Vector containing two types? Not a map, but a sort of Vector<typeA or typeB>.
Regards,
Last edited by Ephracis; 01-14-2007 at 05:48 AM.
|
|
|
01-14-2007, 06:00 AM
|
#2
|
Member
Registered: Oct 2005
Posts: 970
Rep:
|
There are a couple of approaches to this, the ones I am thinking about could use the following
Boost Any or Boost Variant, yet these would require you to know the type or a way of finding the type. So you could therefore using std::vector<void*> (which is what boost uses for pointer vectors) and cast to the correct type, but I feel this defeats your purpose.
Last edited by dmail; 01-14-2007 at 06:03 AM.
|
|
|
01-14-2007, 08:36 AM
|
#3
|
Member
Registered: Jan 2005
Distribution: Archlinux, Debian, Centos
Posts: 222
Rep:
|
Java for instance has the everything is an object aproach. You just return an java.lang.Object
from your method. Maybe these objects have something in common, some common interface or something,
so you can return an (abstract) base type.
|
|
|
01-14-2007, 08:55 AM
|
#4
|
Member
Registered: Oct 2005
Posts: 970
Rep:
|
Quote:
Originally Posted by traene
Java for instance has the everything is an object aproach. You just return an java.lang.Object
from your method. Maybe these objects have something in common, some common interface or something,
so you can return an (abstract) base type.
|
This is how the inner workings of boost Any work, yet the types contained with in the "Any" class need not have any relation to each other.
|
|
|
01-14-2007, 10:14 AM
|
#5
|
Member
Registered: Jun 2005
Location: Indiana, USA
Distribution: OpenBSD, Ubuntu
Posts: 892
Rep:
|
Quote:
Originally Posted by Ephracis
I have a list of objects, the objects can be of two types. So when I call at(int) it can return either a pointer to object of type A or a pointer to an object of type B.
To extend it a little bit, is there a way of managing a Vector containing two types? Not a map, but a sort of Vector<typeA or typeB>.
|
What language are you using? I'm guessing from your description that it's something like C++ or Java. The cleanest way would be to create an abstract class that both typeA and typeB implement. Then your vector would contain instances of that abstract class. Alternatively, in C++ you could use unions to express multiple possible types as a single one. This isn't nearly as clean or safe in C++ as in languages like Ada or OCaml, but it is possible.
|
|
|
01-14-2007, 10:39 AM
|
#6
|
LQ Newbie
Registered: Jan 2007
Location: Austria
Distribution: Ubuntu 8.04 Hardy Heron LTS
Posts: 10
Rep:
|
if it's C++, I would do it like this:
Code:
enum {tpA, tpB} retType_t;
void *at(int i, retType_t *tp)
{
void *fnc;
...
if (...)
{
*tp = tpA;
fnc = A;
}
else
{
*tp = tpB;
fnc = B;
}
return fnc;
}
In this case, the caller knows by the value tp is set to to what class it has to be casted.
|
|
|
01-14-2007, 11:02 AM
|
#7
|
Member
Registered: Oct 2005
Posts: 970
Rep:
|
In some situations you could use this, but if the class is in a hierarchy of classes then you could get splicing of data. Ephracis post some more information, it may be a idea to use a design pattern like visitor and thus let the caller call the correct method and get the correct type.
Last edited by dmail; 01-14-2007 at 11:03 AM.
|
|
|
01-14-2007, 11:12 AM
|
#8
|
Senior Member
Registered: Sep 2004
Location: Sweden
Distribution: Ubuntu, Debian
Posts: 1,109
Original Poster
Rep:
|
I am using C++ and here is how it looks:
I have a DataList which contains a vector of DataGroups and DataItems.
I have a DataGroup which contains a vector of DataGroups and DataItems.
I have a DataItem class.
Look at it as item is a file, group is a directory and list is root.
DataGroup and DataItem both inherits from DataAbstract, but they add a lot of functionality to it.
My object will create a DataList instance and add some groups and items, and within the groups there will be more nested groups and at last the items.. Just like a file tree or something like that, groups in groups, items in groups and everything in one list.
Then, another class will get this DataList and go through it and take different actions if the item is of type DataGroup or DataItem. I am not writing this class, I just export a pointer to my class DataList which this class will then use.
I need a way of just containing and structuring these classes in a simple way and I want DataList and DataGroup to be able to do stuff like add(DataGroup), add(DataItem) and at(int position).
|
|
|
01-14-2007, 11:52 AM
|
#9
|
Member
Registered: Oct 2005
Posts: 970
Rep:
|
It sounds very much like a tree, where a item is a node, list and group are trees.
This may sound condescending have you tried to think and design it like this.
Last edited by dmail; 01-14-2007 at 11:57 AM.
|
|
|
01-14-2007, 05:00 PM
|
#10
|
Member
Registered: Jun 2005
Location: Indiana, USA
Distribution: OpenBSD, Ubuntu
Posts: 892
Rep:
|
What's the difference between DataGroup and DataList? Except for the fact that a DataList is expected by the other function.
You can use DataAbstract to store both types into the same vector, like this:
Code:
#include <iostream>
#include <string>
#include <vector>
class DataAbstract {
public:
virtual std::string get() = 0;
};
class DataGroup : public DataAbstract {
public:
std::string get() {
return "I'm a DataGroup.";
}
};
class DataItem : public DataAbstract {
public:
std::string get() {
return "I'm a DataItem.";
}
};
int main(int argc, char** argv) {
std::vector<DataAbstract*>* v = new std::vector<DataAbstract*>();
v->push_back(new DataGroup());
v->push_back(new DataItem());
std::cout << "Item 0 says \"" << v->at(0)->get() << "\"\n";
std::cout << "Item 1 says \"" << v->at(1)->get() << "\"\n";
if (typeid(*(v->at(0))) == typeid(*(v->at(1)))) {
std::cout << "They're the same type!\n";
std::cout << "Both are type " << typeid(*(v->at(0))).name() << ".\n";
}
else {
std::cout << "They're different types!\n";
std::cout << "Item 0 is of type " << typeid(*(v->at(0))).name() << ".\n";
std::cout << "Item 1 is of type " << typeid(*(v->at(1))).name() << ".\n";
}
return 0;
}
At the end there you can see how to check the dynamic type of the contents of the vector. Note that the name() of a type is implementation defined: with GCC 3.4.3 for example, I see "9DataGroup" and "8DataItem".
|
|
|
01-15-2007, 05:44 AM
|
#11
|
LQ Newbie
Registered: Jan 2007
Location: Austria
Distribution: Ubuntu 8.04 Hardy Heron LTS
Posts: 10
Rep:
|
If I have more time, I will search more of that. Since I am an old Pascal programmer, I know the concept of "Class Pointers", of which I have noticed that there is an equivalent in C++, too. Since you have identical parent classes, this will work. In Delphi, you have to define
Type TMyClassPointer = class of TMyParentClass;
May be this helps you so far that you can google around it for C++.
|
|
|
01-16-2007, 12:57 AM
|
#12
|
Senior Member
Registered: Sep 2004
Location: Sweden
Distribution: Ubuntu, Debian
Posts: 1,109
Original Poster
Rep:
|
There isn't much difference between DataList and DataGroup right now, but the thing is that DataList is what the other classes will see and use, and it will act as root.
I was thinking of using QStack to store the items and groups but I need a way of reordering all items and also get the index where an item is located, this seems a little bit complicated with a QStack.
|
|
|
01-16-2007, 07:23 AM
|
#13
|
Member
Registered: Jun 2005
Location: Indiana, USA
Distribution: OpenBSD, Ubuntu
Posts: 892
Rep:
|
Unless I misunderstand your problem, just make DataList a vector of DataAbstract, then add < and == for DataAbstract (implemented in the children) so you can use <algorithm> functions to sort or search your vector.
|
|
|
All times are GMT -5. The time now is 05:20 AM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|