Archived

This forum has been archived. Please start a new discussion on GitHub.

Generated constructors in derived classes do not pass params correctly to base class

Hello,

When I pass a parameter through a base class constructor it does not seem to get set into the base class member variable. Here is a small repo case to demo
the problem. (Ice version is 3.3.0 for C++)

--- demo.ice. ---
module demo
{
    enum ShapeType {
        Unknown,
        RectangleType,
        TriangleType,
        CircleType,
        SquareType
    };
    class Shape {
        ShapeType type;
    };
    class Circle extends Shape {
        int radius;
    };
    sequence<Shape> ShapeSeq;
};

-- demoTest.cpp --
#include "demo.h"
#include <iostream>
#include <assert.h>

using namespace std;
using namespace demo;

class CircleI : virtual public Circle
{
public:
    CircleI(int rad)
        : Circle(CircleType, rad)
    {
        cerr << "Circle of radius:" << radius 
               << " type:" << type << endl;
        assert(type == CircleType);
    }
};

int main(int,char *[])
{
    ShapeSeq shapes;
    shapes.push_back( new CircleI(20) );
}

When I run this I get the following result.

./demo
Circle of radius:20 type:0
Assertion failed: type == CircleType, file demoTest.cpp, line 15

Compilation abort (core dumped) at Thu Mar 26 10:38:23

Comments

  • bernard
    bernard Jupiter, FL
    Hi John,

    This is expected, because the generated Circle derives from the generated Shape with virtual inheritance.

    With such virtual base class, the constructor of the most derived class needs to initialize each virtual base class, e.g. you would write:
    CircleI(int rad)
            : Shape(CircleType),
              Circle(CircleType, rad)
        {
        }
    

    Otherwise, it's the default Shape constructor that gets called.

    BTW if you add a third class in your Slice class hierarchy and read the generated code, you'll see that the "one-shot" constructor of the most derived class properly calls the constructor of all base classes with data members.

    Best regards,
    Bernard
  • Thanks it works now!
    ./demo
    Circle of radius:20 type:3

    It seems strange to call two base class constructors but it is better than than setting it in the body of the derived constructor which was the only work around that I had.

    Thanks for the prompt reply,
    -john
  • This seems like a really bad thing from the perspective of avoiding duplicate code...now instead of having constructors that neatly cascade, I have a mountain of redundant initialization code that grows with every new class specialization.

    Is there no way around this?
  • bernard
    bernard Jupiter, FL
    Hi Nick,

    There is no way-around, as it is a consequence of mapping Slice class inheritance to virtual inheritance in C++. We've changed this mapping in the upcoming 3.4 release (to use non-virtual inheritance by default) to avoid this often surprising behavior.

    Best regards,
    Bernard