Here is my situation
class base {
};
class child1 {
int data;
};
class child2 {
string data;
};
I want to access data from a base& object. Now, I know I can't do this
directly, but is there any way I could define a virtual "get" method
that could be called on a base& or base* object and return the correct
type?
I've tried declaring a get method in the base class and overriding it
in the child classes, but that gives an error as expected. I can't see
any way to use polymorphism because the return types must differ. 5 1815
This is a decision that needs to be made at compile time, otherwise how
would you know what type of variable to which assign the "get()". That
is, if get() returned both int and string you need to know at compile
time whether to do this
int x = object.get();
or
string x object.get();
Compile time stuff is done with templates, so there's probably a way to
do this with templates, but you need to ask yourself why you're needing
such a thing and decide whether or not it's good design.
[Grr... Google needs to make Groups work with the back button, at least
in Firefox. I hit a link by accident and lost most of this reply from
the first time I typed it. Anyway...]
The short answer is that you can't do it.
The medium answer is that you probably shouldn't do it. See BigBrian's
reply. If you post the context of what you're doing, we might be able
to help you come up with an alternate solution. (There are a couple
ideas below, after the long answer.) But you probably shouldn't have to
do this.
If you really want to do this, read on. There are a couple possible
solutions to do something sorta along the same lines as what you
want...
The long answer is that you can fake it. Make a union type, e.g.
typedef union { int number; string str; } string_or_int;
and return that. Depending on the type of variable you are storing the
result in, do like my_base_object.get_data().number or
my_base_object.get_data().str.
Actually, a better way is to make a discriminated union. It'll require
more typing because you'll have to define a class, but it's not too
hard. Add a union like above, then add another field that you can set
to indicate whether a number or string is stored in the union. Make a
get_integer() and a get_string() function that check this type before
returning, and throw an exception if the function call doesn't match
the type.
The longest answer is that an even better way is to drop the whole idea
in the first place. If you're going to go the route of the (possibly
discriminated) union, you might as well just put the two functions
right in the base class and do it that way. Something like this:
class base {
public:
virtual int get_child1_data() { throw someException("Class isn't a
child1"); }
virtual string get_child2_data() { throw someException("Class
isn't a child2"); }
}
class child1 {
...
public:
virtual int get_child1_data() { return data; }
}
(This is sorta hackish. There is probably a better way to do the same
idea. Actually, some might say the discriminated union idea is better.)
Another idea is if the string is going to be something like "123" you
could make the get function in child2 convert data to an integer and
return that; then the get function would be an int in each of its
occurances and it would all work out. Or, you could convert child1's
data to a string (so the integer 123 to the string "123") and return
that.
If this is still not flexible enough, perhaps you should consider
another language like Ruby where everything is a an object that derives
from one root and thus you don't have to worry about types in the same
sense as your typical imperative languages like C, C++, Java, C#, etc.,
only what operations (methods) the objects support. I think Smalltalk
would work too.
Basically what I'm doing is a simple interpreted programming language.
Because several of the operators work for different types, I wanted to
avoid the "obvious" solution with a discriminated union:
if (x.type == type1)
// Call operator for type1
else if (x.type == type2)
// Call operator for type2
else if (x.type == type 3)
// Call operator for type3
....
Polymorphism isn't the right solution as far as I can tell, and
templates are even messier than the long if..else or switch statements
after jumping through hoops to get them to work. I've looked into the
Boost library, but those are very general and complicated classes where
my need is minimal. Using Boost seems like it would be overkill, for
not really enough gain that I can see at present.
What I have works, but it's ugly and would be difficult to extend if I
added new operators or types.
Duck Dodgers wrote: Basically what I'm doing is a simple interpreted programming language. Because several of the operators work for different types, I wanted to avoid the "obvious" solution with a discriminated union:
if (x.type == type1) // Call operator for type1 else if (x.type == type2) // Call operator for type2 else if (x.type == type 3) // Call operator for type3 ...
Polymorphism isn't the right solution as far as I can tell, and templates are even messier than the long if..else or switch statements after jumping through hoops to get them to work. I've looked into the Boost library, but those are very general and complicated classes where my need is minimal. Using Boost seems like it would be overkill, for not really enough gain that I can see at present.
What I have works, but it's ugly and would be difficult to extend if I added new operators or types.
Yep, been there, very ugly.
In my case, I want a generic "get_value" method that would return
the value of a {variant} field. The field could be integer, boolean,
string, etc. A record would be a collection of fields.
The solution for simple types is to return the value as a string.
Many types can be converted to an from strings.
Otherwise, you are looking at double dispatch and the Visitor
design pattern.
Most implementations of this dilemma use a generic pointer and
an enumerated value indicating the type of the data:
enum Variant_Type
{
Unknown, integer, string, etc
};
struct Variant
{
Variant_Type type;
void * pointer_to_data;
// or perhaps a union here
};
Probably the best route is the Visitor pattern.
--
Thomas Matthews
"Duck Dodgers" <mo*******@hotmail.com> wrote in message class base { };
class child1 { int data; };
class child2 { string data; };
I take it child1, child2 are supposed to derive from base.
Best way is to create an abstract base class Variable. From this derive
Integer and String. class base will have a virtual function that returns a
reference to a Variable.
Related to this will be double dispatch. You can look it up on the
internet.
Idea: If you have a function F1 that takes an Integer and an Integer,
create another function that takes a reference to two Variables and calls F1
after doing a static_cast to convert a reference to a Variable to a
reference to an Integer. If you have a function F2 that takes an Integer
and a String, create another function that again takes a reference to two
Variables and calls F2 after doing a static_cast. Store F1 and F2 in a map
along with the concatenation of typeid -- ie. the function related to F1 has
key strcat(typeid(Integer).name(), typeid(Integer).name()), and the function
related to F2 has key strcat(typeid(Integer).name(), typeid(String).name()).
Then create your generic function F that takes a reference to two Variables
and looks up the typeid in the map.
I want to access data from a base& object. Now, I know I can't do this directly, but is there any way I could define a virtual "get" method that could be called on a base& or base* object and return the correct type?
I've tried declaring a get method in the base class and overriding it in the child classes, but that gives an error as expected. I can't see any way to use polymorphism because the return types must differ. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Chris Stromberger |
last post by:
When issuing updates in mysql (in the console window), mysql will tell
you if any rows matched and how many rows were updated (see below). I
know...
|
by: Dave Opstad |
last post by:
In this snippet:
d = {'x': 1}
value = d.get('x', bigscaryfunction())
the bigscaryfunction is always called, even though 'x' is a valid key....
|
by: Me |
last post by:
Hi, I would like learn from people with experience in C++, which of the
following styles of way to construct "get/set" member functions would be the...
|
by: kelvin |
last post by:
How do I use get data in a url sent from aform on an other page. All i want
to do is take this data and display it on the page.
thanking you in...
|
by: Eitan |
last post by:
Hello,
I would like to know about the methods : post and get of ASP.
What is the difference between them.
Need some samples, and explanation,...
|
by: Javaman59 |
last post by:
This is probably common knowledge to .Net gurus, but please bear with me
while I share a discovery with the group...
I needed to create a public...
|
by: martyn_wynne |
last post by:
Hi,
I have found a odd one, my submit button is not submitting on a
method="get" form after using any form of DataBind?
Has anyone struck this...
|
by: Bsr |
last post by:
What is the difference between for the following methods.
"GET", "HEAD", "PUT" or "POST".
Ex:my $req =HTTP::Request->new(GET =>$url1);
...
|
by: =?Utf-8?B?cmFuZHkxMjAw?= |
last post by:
The code below goes through all the methods in the given dll. I'm wondering
how I can modify this to only get methods with a specific custom...
|
by: jalbright99669 |
last post by:
Am having a bit of a time with URL Rewrite. I need to incorporate http to https redirect with a reverse proxy. I have the URL Rewrite rules made...
|
by: antdb |
last post by:
Ⅰ. Advantage of AntDB: hyper-convergence + streaming processing engine
In the overall architecture, a new "hyper-convergence" concept was...
|
by: Matthew3360 |
last post by:
Hi there. I have been struggling to find out how to use a variable as my location in my header redirect function.
Here is my code.
...
|
by: Arjunsri |
last post by:
I have a Redshift database that I need to use as an import data source. I have configured the DSN connection using the server, port, database, and...
|
by: WisdomUfot |
last post by:
It's an interesting question you've got about how Gmail hides the HTTP referrer when a link in an email is clicked. While I don't have the specific...
|
by: Matthew3360 |
last post by:
Hi,
I have been trying to connect to a local host using php curl. But I am finding it hard to do this. I am doing the curl get request from my web...
|
by: Carina712 |
last post by:
Setting background colors for Excel documents can help to improve the visual appeal of the document and make it easier to read and understand....
|
by: BLUEPANDA |
last post by:
At BluePanda Dev, we're passionate about building high-quality software and sharing our knowledge with the community. That's why we've created a SaaS...
|
by: Rahul1995seven |
last post by:
Introduction:
In the realm of programming languages, Python has emerged as a powerhouse. With its simplicity, versatility, and robustness, Python...
| |