Is setting substruct values to values returned by pure virtual functions safe in an object constructor?

StackOverflow https://stackoverflow.com/questions/20451686

  •  30-08-2022
  •  | 
  •  

Question

Consider (note some code removed from object, i.e. constructors/destructors and some variables):

struct object {
    virtual bool object_is_solid() = 0;
    virtual bool object_is_visible() = 0;
    virtual bool object_is_persistent() = 0;
    virtual real_t object_depth() = 0;
    virtual real_t object_sprite_index() = 0;
    virtual real_t object_mask_index() = 0;

    struct object_properties {
      bool solid;
      bool visible;
      bool persistent;
      real_t depth;
      real_t sprite_index;
      real_t mask_index;
      real_t image_alpha;
      real_t image_angle;
      real_t image_blend;
      real_t image_index;
      real_t image_speed;
      real_t image_xscale;
      real_t image_yscale;
      real_t hfriction;
      real_t vfriction;
      real_t hgravity;
      real_t vgravity;
      real_t hspeed;
      real_t vspeed;
    } properties;

    void initialize_properties(object::object_properties& prop);
}

and

  object::object(unsigned long id, real_t x, real_t y)
    : id(id), xstart(x), ystart(y), x(x), y(y), xprevious(x), yprevious(y), properties{} {
    this->initialize_properties(this->properties);
  }

  void object::initialize_properties(object::object_properties& prop) {
    prop.solid = this->object_is_solid();
    prop.visible = this->object_is_visible();
    prop.persistent = this->object_is_persistent();
    prop.depth = this->object_depth();
    prop.sprite_index = this->object_sprite_index();
    prop.mask_index = this->object_mask_index();
    prop.image_alpha = 1;
    prop.image_speed = 1;
    prop.image_xscale = 1;
    prop.image_yscale = 1;
  }

Notice the usage of initialize_properties.

  1. Is this even safe? If I inline initialize_properties manually, clang refuses to compile it because it's calling pure virtual functions in the constructor.
  2. Is there a better way for me to initialise properties than what I am doing right now?
Was it helpful?

Solution

Short answer: don't do it.

Explanation: When object is constructed, the object is of type object, not the derived class yet. Let's call the derived class my_object.

Any virtual function (pure or not) that your in object's constructor will call object's version. Only in the body of my_object::my_object() the object type is my_object, not before.

The solution is to separate construction from initialization. From my_object::my_object() call a virtual function Initialize or better, expose it as a public method so the code that created the my_object instance will call it to initialize the object.

Example:

my_object o;
o.Init(params);

OTHER TIPS

No, it's not safe.

I'm going to refractor the code so that it's necessary the user call a member function to perform this initialisation. It's not as automatic as I'd like, but it's probably for the best.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top