classes in a class

Discussion in 'C++' started by Joe C, Sep 16, 2004.

  1. Joe C

    Joe C Guest

    I have a class that performs transformations on data streams. As written,
    the class constructor takes several parameters and a data-source to produce
    it's stream.

    I have the need to combine the output of two instances of this class to
    generate a third data stream. (think eg of applying a filters to audio)

    When I do this, the parameters that I supply the second class are dependent
    upon the state of the system after the first transform has occured.

    I have been accomplishing this by using a function outside the class that
    instantiates the two classes as the information needed to instantiate them
    becomes available. Once both objects are built, their output is combined
    and the function exits, the objects are destroyed, and the caller gets his
    transformed data.

    I don't like this solution because my objects cease to exist once I return
    the data...but I want to keem them around for a while longer.

    So...as a solution, I decided to create a new class that would hold the two
    instances of my transforming class objects and return the combined data. My
    problem is...how can I construct my two member-data objects when the
    construction parameters of the second object depend upon having made some
    calculations on the first, successfully constructed object?

    I can't supply the constructor parameters for the second object in the
    initialization list because those parameters require some processing *after*
    the first object is constructed.

    Thanks for your thoughts

    Joe
     
    Joe C, Sep 16, 2004
    #1
    1. Advertising

  2. Joe C wrote:
    > I have a class that performs transformations on data streams. As written,
    > the class constructor takes several parameters and a data-source to produce
    > it's stream.
    >
    > I have the need to combine the output of two instances of this class to
    > generate a third data stream. (think eg of applying a filters to audio)
    >
    > When I do this, the parameters that I supply the second class are dependent
    > upon the state of the system after the first transform has occured.
    >
    > I have been accomplishing this by using a function outside the class that
    > instantiates the two classes as the information needed to instantiate them
    > becomes available. Once both objects are built, their output is combined
    > and the function exits, the objects are destroyed, and the caller gets his
    > transformed data.
    >
    > I don't like this solution because my objects cease to exist once I return
    > the data...but I want to keem them around for a while longer.
    >
    > So...as a solution, I decided to create a new class that would hold the two
    > instances of my transforming class objects and return the combined data. My
    > problem is...how can I construct my two member-data objects when the
    > construction parameters of the second object depend upon having made some
    > calculations on the first, successfully constructed object?
    >
    > I can't supply the constructor parameters for the second object in the
    > initialization list because those parameters require some processing *after*
    > the first object is constructed.


    Make the second subobject a dynamic one and construct it using 'new':

    class myclass {
    myfirstauxiliaryclass aux1;
    mysecondauxiliaryclass *paux2;
    public:
    myclass() : aux1(parameters) {
    somecalculations(aux1);
    paux2 = new mysecondauxiliaryclass(otherparameters);
    }
    };

    Victor
     
    Victor Bazarov, Sep 16, 2004
    #2
    1. Advertising

  3. Joe C

    Joe C Guest

    "Victor Bazarov" <> wrote in message > Make the
    second subobject a dynamic one and construct it using 'new':
    >
    > class myclass {
    > myfirstauxiliaryclass aux1;
    > mysecondauxiliaryclass *paux2;
    > public:
    > myclass() : aux1(parameters) {
    > somecalculations(aux1);
    > paux2 = new mysecondauxiliaryclass(otherparameters);
    > }
    > };
    >
    > Victor


    Thanks Victor. This is exactly what I need. I guess it should have been
    obvious to me but...well...it wasn't 8-\ Thanks again for 'getting' my
    question, and giving me a straight forward solution.
     
    Joe C, Sep 16, 2004
    #3
  4. Joe C

    Cy Edmunds Guest

    "Joe C" <> wrote in message
    news:w0l2d.145768$...
    >
    > "Victor Bazarov" <> wrote in message > Make the
    > second subobject a dynamic one and construct it using 'new':
    > >
    > > class myclass {
    > > myfirstauxiliaryclass aux1;
    > > mysecondauxiliaryclass *paux2;
    > > public:
    > > myclass() : aux1(parameters) {
    > > somecalculations(aux1);
    > > paux2 = new mysecondauxiliaryclass(otherparameters);
    > > }
    > > };
    > >
    > > Victor

    >
    > Thanks Victor. This is exactly what I need. I guess it should have been
    > obvious to me but...well...it wasn't 8-\ Thanks again for 'getting' my
    > question, and giving me a straight forward solution.
    >
    >


    It isn't quite as straight forward as you might think. The code as written
    has a memory leak -- operator delete is never called. Of course you can add
    a destructor with a delete statement, but then you really should add a copy
    constructor and an assignment operator, remembering of course to avoid the
    x=x bug in an exception-safe matter. No big deal, but still...

    You could use a smart pointer, but it can also be done without any pointers
    at all:

    class two_things
    {
    private:
    thing a;
    thing b;
    public:
    two_things(arg_type arg) : a(arg), b(a) {}
    // other stuff
    };

    This may look dangerous, but the standard guarantees that member variables
    are intialized in the order they are declared. Thus a is constructed before
    b and is safe to use as an argument for b's constructor.

    --
    Cy
    http://home.rochester.rr.com/cyhome/
     
    Cy Edmunds, Sep 17, 2004
    #4
  5. "Cy Edmunds" <> wrote...
    > "Joe C" <> wrote in message
    > news:w0l2d.145768$...
    >>
    >> "Victor Bazarov" <> wrote in message > Make the
    >> second subobject a dynamic one and construct it using 'new':
    >> >
    >> > class myclass {
    >> > myfirstauxiliaryclass aux1;
    >> > mysecondauxiliaryclass *paux2;
    >> > public:
    >> > myclass() : aux1(parameters) {
    >> > somecalculations(aux1);
    >> > paux2 = new mysecondauxiliaryclass(otherparameters);
    >> > }
    >> > };
    >> >
    >> > Victor

    >>
    >> Thanks Victor. This is exactly what I need. I guess it should have been
    >> obvious to me but...well...it wasn't 8-\ Thanks again for 'getting' my
    >> question, and giving me a straight forward solution.
    >>
    >>

    >
    > It isn't quite as straight forward as you might think. The code as written
    > has a memory leak -- operator delete is never called. Of course you can
    > add
    > a destructor with a delete statement, but then you really should add a
    > copy
    > constructor and an assignment operator, remembering of course to avoid the
    > x=x bug in an exception-safe matter. No big deal, but still...
    >
    > You could use a smart pointer, but it can also be done without any
    > pointers
    > at all:
    >
    > class two_things
    > {
    > private:
    > thing a;
    > thing b;
    > public:
    > two_things(arg_type arg) : a(arg), b(a) {}
    > // other stuff
    > };
    >
    > This may look dangerous, but the standard guarantees that member variables
    > are intialized in the order they are declared. Thus a is constructed
    > before
    > b and is safe to use as an argument for b's constructor.


    Yes, and to perform that extra calculation you could declare a dummy member
    and initialise it with the value returned by that calculation function:

    class two_things
    {
    thing_one a;
    int dummy;
    thing_two b;

    int some_extra_calculations(thing_one&);

    public:
    two_things(some_arguments)
    : a(whatever)
    , dummy(some_extra_calculations(a)
    , b(something_else)
    {
    }
    };

    Given certain assumptions, everything is possible.

    V
     
    Victor Bazarov, Sep 17, 2004
    #5
  6. Joe C

    Joe C Guest

    "Cy Edmunds" <> wrote in message
    news:n3t2d.232865$...
    > "Joe C" <> wrote in message
    > news:w0l2d.145768$...
    >>
    >> "Victor Bazarov" <> wrote in message > Make the
    >> second subobject a dynamic one and construct it using 'new':
    >> >
    >> > class myclass {
    >> > myfirstauxiliaryclass aux1;
    >> > mysecondauxiliaryclass *paux2;
    >> > public:
    >> > myclass() : aux1(parameters) {
    >> > somecalculations(aux1);
    >> > paux2 = new mysecondauxiliaryclass(otherparameters);
    >> > }
    >> > };
    >> >
    >> > Victor

    >>
    >> Thanks Victor. This is exactly what I need. I guess it should have been
    >> obvious to me but...well...it wasn't 8-\ Thanks again for 'getting' my
    >> question, and giving me a straight forward solution.
    >>
    >>

    >
    > It isn't quite as straight forward as you might think. The code as written
    > has a memory leak -- operator delete is never called. Of course you can
    > add
    > a destructor with a delete statement, but then you really should add a
    > copy
    > constructor and an assignment operator, remembering of course to avoid the
    > x=x bug in an exception-safe matter. No big deal, but still...


    Thanks for the comments. I used Vics method, and...as I guess Victor
    guessed, we were on the same page regarding cleaning up memory.

    >
    > You could use a smart pointer, but it can also be done without any
    > pointers
    > at all:
    >
    > class two_things
    > {
    > private:
    > thing a;
    > thing b;
    > public:
    > two_things(arg_type arg) : a(arg), b(a) {}
    > // other stuff
    > };
    >
    > This may look dangerous, but the standard guarantees that member variables
    > are intialized in the order they are declared. Thus a is constructed
    > before
    > b and is safe to use as an argument for b's constructor.
    >

    I don't think this technique will work, unless I modify the 'thing' class to
    do the calculations that b needed...which doesn't make logical sense for
    this class. I can't use your method because the method of generating the
    parameters needed to instantiate b from a requires about 10 lines of code.
    Anyway, thanks for offering another approach.
     
    Joe C, Sep 17, 2004
    #6
  7. Joe C

    Joe C Guest

    "Victor Bazarov" <> wrote in message
    news:t8t2d.103477$3l3.48115@attbi_s03...
    > "Cy Edmunds" <> wrote...
    >> "Joe C" <> wrote in message
    >> news:w0l2d.145768$...
    >>>
    >>> "Victor Bazarov" <> wrote in message > Make the
    >>> second subobject a dynamic one and construct it using 'new':
    >>> >
    >>> > class myclass {
    >>> > myfirstauxiliaryclass aux1;
    >>> > mysecondauxiliaryclass *paux2;
    >>> > public:
    >>> > myclass() : aux1(parameters) {
    >>> > somecalculations(aux1);
    >>> > paux2 = new mysecondauxiliaryclass(otherparameters);
    >>> > }
    >>> > };
    >>> >
    >>> > Victor
    >>>
    >>> Thanks Victor. This is exactly what I need. I guess it should have
    >>> been
    >>> obvious to me but...well...it wasn't 8-\ Thanks again for 'getting' my
    >>> question, and giving me a straight forward solution.
    >>>
    >>>

    >>
    >> It isn't quite as straight forward as you might think. The code as
    >> written
    >> has a memory leak -- operator delete is never called. Of course you can
    >> add
    >> a destructor with a delete statement, but then you really should add a
    >> copy
    >> constructor and an assignment operator, remembering of course to avoid
    >> the
    >> x=x bug in an exception-safe matter. No big deal, but still...
    >>
    >> You could use a smart pointer, but it can also be done without any
    >> pointers
    >> at all:
    >>
    >> class two_things
    >> {
    >> private:
    >> thing a;
    >> thing b;
    >> public:
    >> two_things(arg_type arg) : a(arg), b(a) {}
    >> // other stuff
    >> };
    >>
    >> This may look dangerous, but the standard guarantees that member
    >> variables
    >> are intialized in the order they are declared. Thus a is constructed
    >> before
    >> b and is safe to use as an argument for b's constructor.

    >
    > Yes, and to perform that extra calculation you could declare a dummy
    > member
    > and initialise it with the value returned by that calculation function:
    >
    > class two_things
    > {
    > thing_one a;
    > int dummy;
    > thing_two b;
    >
    > int some_extra_calculations(thing_one&);
    >
    > public:
    > two_things(some_arguments)
    > : a(whatever)
    > , dummy(some_extra_calculations(a)
    > , b(something_else)
    > {
    > }
    > };
    >
    > Given certain assumptions, everything is possible.
    >
    > V


    The class actually instantiates with a struct and a container ...the dummy
    method would have gotten a little ugly. For this particular problem, I
    think the pointer method you first offered was the more natural approach
    compared to forcing it to happen in the initialization list. The only
    downside is that one "thing" gets.treatment() while the other "thing"
    gets->treatment() which is slightly awkward to have two very similar things
    requiring different syntax. However, as this is hidden in the two_things
    class, it doesn't really matter much.

    Thanks guys.
     
    Joe C, Sep 17, 2004
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. David

    Classes within classes

    David, Jul 21, 2005, in forum: ASP .Net
    Replies:
    2
    Views:
    4,959
    David
    Jul 22, 2005
  2. lonelyplanet999
    Replies:
    1
    Views:
    2,233
    VisionSet
    Nov 13, 2003
  3. E11
    Replies:
    1
    Views:
    4,801
    Thomas Weidenfeller
    Oct 12, 2005
  4. christopher diggins
    Replies:
    16
    Views:
    761
    Pete Becker
    May 4, 2005
  5. Joseph Turian
    Replies:
    5
    Views:
    603
Loading...

Share This Page