A basic conceptual C++ question.
(This in some ways ties into allbery
's recently-posted essay
on online communities. Most of my dearest friends, and much of my social life, link back in some way to the online communities that I found shortly after I started graduate school, which were places that I could ask this sort of question, and full of people who'd be interested in talking about the answer. In the last few years, they've nearly all drifted apart -- so I'm trying the experiment of asking here, to see what comes of it.)
So, I'm learning C++, from what I suspect is somewhat of an interesting perspective these days; I've been programming for two decades, been doing object-oriented programming as part of my paying work for two or three years, and maintain a Windows port of a large open-source C++ program. This means that I've got sort of weird gaps in what I know -- such as the fact that I wrote my first abstract class definition ... yesterday.
In any case, the problem is this: I'm writing a parser. It breaks a stream of characters up into tokens, so I've got an abstract class for "token" and a bunch of derived classes for the various kinds of tokens (names, parentheses, whitespace, etc.). And so I went off to write a function that takes in a reference to the character stream, bites off a bit of it, and returns a token object, figuring that would be pretty trivial.
Except that, as best I can tell, I can't do that in C++.
Because, you see, I want to return an arbitrary token object, which might be an instance of any of the various derived token classes, and so the return type from the function ought to be declared as token, and my C++ manual tells me that "an abstract class may not be used as ... a function return type." I've got to use a pointer to the abstract class, or a reference to it, instead. But that's no good, because then I have to worry about where the object that's pointed to comes from, and in particular I have to worry about who frees the memory when it goes away. Which is an almighty pain, because this is a function result, and might very easily just be passed as an argument to another function, and then who knows who's supposed to free the memory?
I'd also like to be able to do a nice, simple, "A = B" assignment, where B is a token object, and get a copy of the object in A. Except that the same problem arises; I can't declare A as an abstract token; I have to declare it as a pointer or reference to one, and I get the same sort of problems; I want a copy of the token, not a reference to the same piece of memory.
As best I can figure from what I know, the only way to make this work is to write a wrapper class that contains a pointer to the abstract class (and the derived classes), and has a destructor that clears the pointed-at memory. And then, ugh, it also has to explicitly handle all the assignment-is-copying stuff to construct a new token-object for the result, and I'm not sure what happens if one of these gets passed by value, but I know if I'm not careful I'll get a copy of the pointer and a destructor that clears it when the function ends, leaving the original pointer pointing to garbage.
There's got to be an easier way, right? Or have I just been spoiled by using a dynamically-typed language to learn class inheritance? Current Mood: perplexed