Class-related queries [was: Re: 'Undefined reference' linking errors]

Joseph Wakeling joseph.wakeling at gmail.com
Fri Apr 9 06:56:02 PDT 2010


Ali Çehreli wrote:
> I have experience with C++ and still don't understand why opCall exists.
> :) I think I heard that opCall was needed to create struct objects
> before structs had constructors in D.
>
> Now structs do have constructors, which sometimes conflict with opCall. :)

I also have some C++ experience, but it seems to be confusing as much as
complementary with respect to D ... :-)

Current source of confusion relates to declaring objects of a class whose
constructor takes input -- confusion because I can write,

        class Foo
        {
                int x;
                uint y;

                this()
                {
                        x = -1;
                        y = 2;
                }
        }

        void main()
        {
                Foo f;
        }

and have no problem, but if instead the constructor is,

        this(int z)
        {
                x = z;
                y = 2;
        }

... it seems like I have to write instead,

        auto f = new Foo(-1);

... and if I write as per C++,

        Foo f(-1);

... I get back a compiler error: "found 'f' when expecting ';' following
'statement'".  Am I right in thinking that the 'new' syntax is necessary when the
class has a constructor which takes input?

This creates confusion also because in C++ one associates 'new' with dynamic
allocation of memory, and it requires a consequent 'delete' statement.  I know
that D has GC, and I know that it also has 'delete' statements, but ... this one
is 'ouch' for me :-P

In my own code (cleaned up, attached following this email, and now working), I
note the line,

        auto aw = new AvgWeighted(ratings,reputationUser,reputationObject);

where if I write instead,

        AvgWeighted aw(ratings,reputationUser,reputationObject);

... I get the error:

        Error: ratings is used as a type
        Error: cannot have parameter of type void
        Error: reputationUser is used as a type
        Error: cannot have parameter of type void
        Error: reputationObject is used as a type
        Error: cannot have parameter of type void

... which is difficult to understand, but I presume it relates to the fact that an
array is a class and not a value.

Apologies if these are relatively trivial questions -- I am sure they will all
become clearer once Andrei Alexandrescu's book is out ... :-)

Thanks & best wishes,

    -- Joe


///////// My code ....

struct Rating
{
        uint u;   // user ID
        uint o;   // object ID
        double r; // rating value
}

class Reputation
{
        this() {}
        this(ref Rating[] ratings,
             ref double[] reputationUser,
             ref double[] reputationObject) {}
}

class AvgWeighted : Reputation
{
        double[] weightSum;

        this(){}

        this(ref Rating[] ratings,
             ref double[] reputationUser,
             ref double[] reputationObject)
        {
                opCall(ratings,reputationUser,reputationObject);
        }

        void opCall(ref Rating[] ratings,
                    ref double[] reputationUser,
                    ref double[] reputationObject)
        {
                weightSum.length = reputationObject.length;
                weightSum[] = 0;

                reputationObject[] = 0;

                foreach(ref Rating r; ratings) {
                        reputationObject[r.o] += reputationUser[r.u]*r.r;
                        weightSum[r.o] += reputationUser[r.u];
                }

                foreach(uint o, ref double r; reputationObject)
                        r /= weightSum[o];
        }
}

class AvgArithmetic : AvgWeighted
{
        this(ref Rating[] ratings,
             ref double[] reputationUser,
             ref double[] reputationObject)
        {
                opCall(ratings,reputationUser,reputationObject);
        }

        void opCall(ref Rating[] ratings,
                    ref double[] reputationUser,
                    ref double[] reputationObject)
        {
                reputationUser[] = 1;
                super.opCall(ratings,reputationUser,reputationObject);
        }
}

void main()
{
        Rating[] ratings;
        double[] reputationUser;
        double[] reputationObject;

        foreach(uint u; 0..999)
                reputationUser ~= 0.1*(u%3);

        reputationObject.length = 1;
        reputationObject[] = 0;

        foreach(uint u;0..reputationUser.length) {
                Rating _r = {u,0,(u%3)};
                writefln("%u %g",_r.u,_r.r);
                ratings ~= _r;
        }

        auto aw = new AvgWeighted(ratings,reputationUser,reputationObject);
        aw(ratings,reputationUser,reputationObject);

        foreach(double o; reputationObject)
                writefln("%g",o);
}


More information about the Digitalmars-d-learn mailing list