Problem with Object Names

Warning! Some information on this page is older than 5 years now. I keep it for reference, but it probably doesn't reflect my current knowledge and beliefs.

May 2010

At least I've started coding my new reflection system which I hope to use for all the stuff I do at home. I'll write about all the assumptions and decisions behind it another time, but today I'd only like to share my thoughts about a little problem I have with object names. I want my abstract base class for all objects to return its name/title to be shown as the name of a tree node in the editor. But interface should theoretically be separate from implementation, so I want an object to be able to simply store its name in some string field or alternatively to build it each time from some internal parameters. Now the question arises how should the interface for fetching this name look like? It turns out to be nontrivial problem in C++, even if I use STL strings instead of char*. Two solutions are possible:

virtual GetName1(std::string &out) = 0;
virtual const std::string & GetName2() = 0;

If some object type stores its name in a std::string Name; field, solution (2) is better because it just returns a reference to its name.

std::string Name;
virtual const std::string & GetName2() { return Name; }

Solution (1) would involve unnecessary copying of the string each time it is fetched:

std::string Name;
virtual GetName1(std::string &out) { out = Name; }

But if an object wants to build its title from some parameters, solution (1) is better:

unsigned Param1, Param2;
virtual GetName1(std::string &out) {
  out = "Params: " + UintToStr(Param1) + ", " + UintToStr(Param2);

Using solution (2) here is possible only if we cache built string in a field. Lazy evaluation could be done here. It's not very bad idea, but involves more coding.

unsigned Param1, Param2;
std::string CachedName;
virtual const std::string & GetName2() {
  CachedName = "Params: " + UintToStr(Param1) + ", " + UintToStr(Param2);
  return CachedName;

Obviously the simplest and most "universal" solution with just returning std::string by value is inefficient in each case because it involves lots of copying.

virtual std::string GetName3() = 0; // Boo!

Finally I've decided to use (1), but I don't like the thought that such problem exists. In C# we wouldn’t have to make a compromise, because there strings are immutable, passed by reference and automatically freed by the garbage collector. We can just do this and the implementation is efficient in every situation:

abstract class Base {
  public abstract string GetName();

class Derived1 : Base {
  private string Name;
  public override string GetName() { return Name; }

class Derived2 : Base {
  private uint Param1, Param2;
  public override string GetName() {
    return string.Format("Params: {0}, {1}", Param1, Param2);

Comments | #c++ Share


[Download] [Dropbox] [pub] [Mirror] [Privacy policy]
Copyright © 2004-2020