views:

318

answers:

2

Hi, I'd like to be able to initialize a derived class from a base class, like so:

class X {
   public:
   X() : m(3) {}
   int m;
};

class Y : public X {
   public: 
   Y() {}
   Y(const & X a)  : X(a) {}
};

Is there anything dangerous or unusual by doing that? I want it because I'm deserializing a bunch of objects who's type I don't immediately know, so I basically want to use X just as some temp storage while I'm reading the whole serialized file, and then create my Y objects (and W, X, Y objs, depending on the data) using that data afterwards. Maybe there's a easier way I'm missing.

Thanks!

+3  A: 

There should be no problem with this as long as X has a correct copy ctor (auto-generated or not) and you set the other members of Y (if any) to appropriate defaults.

I assume that Y would have some setter methods to update Y with the results of subsequent information from the serialization stream?

Also note that your Y from an X constructor should have a signature that looks more like:

Y( X const & a)   // the X was in an invalid place before
Michael Burr
+2  A: 

Is there anything dangerous or unusual by doing that?

If Y has any data members of its own (not in the base class), they won't be initialized.

class Y : public X {
   public: 
   Y() {}
   Y(const X& a) : X(a)
   {
     //'n' hasn't been initialized!
   }
   int n;
};

If Y doesn't have any data members of its own, why is it a distinct subclass? Is it so that it can override virtual members of X?

It's possible that if X is supposed to be subclassed like this, then it ought to be an abstract class with pure-virtual methods which it's impossible to instantiate by itself.

Instead of what you're suggesting, consider containment instead of subclassing (Y "has a" X instead of Y "is a" X):

class IAnInterface
{
public:
  virtual ~IAnInterface();
  virtual void SomeMethod() = 0;
  virtual void AnotherMethod() = 0;
}

class Y : public IAnInterface {
  public: 
  Y(const X& x) : m_x(x)
  {
  }
  X m_x;
  virtual void SomeMethod() { ... an implementation ... }
  virtual void AnotherMethod() { ... another implementation ... }
};
ChrisW
yes, it is because I want Y to override virtual methods; no separate data members.
Steve
Instead I suggest (but without having articulated a reason for suggesting it) that you declare your various virtual methods in some pure-virtual interface, have no virtual methods in X (which is instead a POD Plain Old Data class), and have your leaf classes like Y subclass the interface and contain (not inherit from) the data.
ChrisW