Re: Undefined reference to...

Discussion in 'C++' started by Andrea Crotti, Nov 10, 2010.

  1. The other class is by the way
    class Beacon : public Packet, public Serializable

    is it possible that multiple inheritance makes things harder in this case?
     
    Andrea Crotti, Nov 10, 2010
    #1
    1. Advertising

  2. Andrea Crotti <> writes:

    > The other class is by the way
    > class Beacon : public Packet, public Serializable
    >
    > is it possible that multiple inheritance makes things harder in this case?


    Ok apparently I got it, if I don't implement something it doesn't work

    With this is fine
    virtual void writeBuffer() {}

    With this stupid example I clarified my mind

    class Base
    {
    public:
    Base() {}
    virtual void printOut();
    };

    class Extended : public Base
    {
    public:
    Extended() {}
    void printOut() { cout << "hello"; }
    };

    (like this it doesn't work).

    Would be best to have
    virtual void writeBuffer() = 0

    to make it abstract, BUT then I have a static function that would
    construct an object of subclass of Packet. IF there is a pure function
    in the class definition than I'm not allowed to return a Packet (even if
    I know that it will be always a subclass of it).

    Now way to force the compiler about that?

    And also, why the hell just declaring it and implementing it in every
    subclass doesn't work?
    I mean the compiler should see it's actually implemented everywhere, so
    what's the problem?
     
    Andrea Crotti, Nov 10, 2010
    #2
    1. Advertising

  3. * Andrea Crotti, on 10.11.2010 18:22:
    > Andrea Crotti<> writes:
    >
    >> > The other class is by the way
    >> > class Beacon : public Packet, public Serializable
    >> >
    >> > is it possible that multiple inheritance makes things harder in this case?

    > Ok apparently I got it, if I don't implement something it doesn't work


    That seems to be a correct assessment. Non-implemented features don't work.


    > With this is fine
    > virtual void writeBuffer() {}


    If you say so.


    > With this stupid example I clarified my mind
    >
    > class Base
    > {
    > public:
    > Base() {}
    > virtual void printOut();
    > };
    >
    > class Extended : public Base
    > {
    > public:
    > Extended() {}
    > void printOut() { cout<< "hello"; }
    > };


    Good. A clear mind is very nice.


    > (like this it doesn't work).


    Parse error. Something is like something, and something does not work. What are
    you talking about?


    > Would be best to have
    > virtual void writeBuffer() = 0


    Sure, but where and for what?


    > to make it abstract, BUT then I have a static function that would
    > construct an object of subclass of Packet. IF there is a pure function
    > in the class definition than I'm not allowed to return a Packet (even if
    > I know that it will be always a subclass of it).


    Right, you can't have an object where the most derived type is abstract.


    > Now way to force the compiler about that?


    No.


    > And also, why the hell just declaring it and implementing it in every
    > subclass doesn't work?


    Parse error again.


    > I mean the compiler should see it's actually implemented everywhere, so
    > what's the problem?


    Well, that's what I'm wondering: what is the problem you're talking about?

    Possibly I could find out by looking at your original posting.

    But I don't think it's fair that I and other out to help you should do a lot of
    work to figure out what you're talking about. Please try to convey what you're
    talking about. "It doesn't work" out of context says nothing, in particular, "It
    doesn't work" doesn't say what "It" is.


    Cheers & hth.,

    - Alf

    --
    blog at <url: http://alfps.wordpress.com>
     
    Alf P. Steinbach /Usenet, Nov 10, 2010
    #3
  4. "Alf P. Steinbach /Usenet" <> writes:
    > Well, that's what I'm wondering: what is the problem you're talking about?
    >
    > Possibly I could find out by looking at your original posting.
    >
    > But I don't think it's fair that I and other out to help you should do
    > a lot of work to figure out what you're talking about. Please try to
    > convey what you're talking about. "It doesn't work" out of context
    > says nothing, in particular, "It doesn't work" doesn't say what "It"
    > is.



    Sorry you're right I was not clear, I was just continuing the
    conversation with myself that's why...

    Anyway I rephrase, first question is why this below doesn't find the
    reference to the vtable?

    class Base
    {
    public:
    virtual void printOut();
    };

    class Extended : public Base
    {
    public:
    void printOut() { cout << "hello"; }
    };

    The only subclass actually implements the method I want, so should not
    that be enough?
    Or maybe it complains because the vtable is constructed at runtime
    (giving the possibility of bad crashes if nothing is found)?

    The second question was if it was possible to do something like

    class Extended;

    class Base
    {
    public:
    virtual void printOut() = 0;
    static Base getLower() {
    Extended e;
    return e;
    }
    };

    class Extended : public Base
    {
    public:
    void printOut() { cout << "hello"; }
    };

    Apparently not if I understand, then I'll find some other ways..
     
    Andrea Crotti, Nov 10, 2010
    #4
  5. * Andrea Crotti, on 10.11.2010 19:08:
    > "Alf P. Steinbach /Usenet"<> writes:
    >> Well, that's what I'm wondering: what is the problem you're talking about?
    >>
    >> Possibly I could find out by looking at your original posting.
    >>
    >> But I don't think it's fair that I and other out to help you should do
    >> a lot of work to figure out what you're talking about. Please try to
    >> convey what you're talking about. "It doesn't work" out of context
    >> says nothing, in particular, "It doesn't work" doesn't say what "It"
    >> is.

    >
    >
    > Sorry you're right I was not clear, I was just continuing the
    > conversation with myself that's why...
    >
    > Anyway I rephrase, first question is why this below doesn't find the
    > reference to the vtable?
    >
    > class Base
    > {
    > public:
    > virtual void printOut();
    > };
    >
    > class Extended : public Base
    > {
    > public:
    > void printOut() { cout<< "hello"; }
    > };
    >
    > The only subclass actually implements the method I want, so should not
    > that be enough?
    > Or maybe it complains because the vtable is constructed at runtime
    > (giving the possibility of bad crashes if nothing is found)?


    The compiler doesn't know that you're not creating any pure Base instances.

    And it doesn't care.

    A virtual member function, except a pure virtual member (that's a one with "= 0"
    at the end) must have an implementation, so that the compiler can very
    mechanically put the address of that implementation in the vtable, or use it in
    whatever scheme it uses as an alternative to vtables.


    > The second question was if it was possible to do something like
    >
    > class Extended;
    >
    > class Base
    > {
    > public:
    > virtual void printOut() = 0;
    > static Base getLower() {
    > Extended e;
    > return e;
    > }
    > };
    >
    > class Extended : public Base
    > {
    > public:
    > void printOut() { cout<< "hello"; }
    > };
    >
    > Apparently not if I understand, then I'll find some other ways..


    Problems with the above include

    * 'getLower' attempts to return an object of abstract class.

    * A local variable is declared with incomplete type 'Extended'.

    * If those obstacles weren't in the way, 'getLower' would perform
    a *slicing*, returning only the Base part of 'e', and then of type
    'Base'.

    It's not clear what you're attempting, but it may be that you want a Meyers'
    singleton:

    class Base
    {
    public:
    virtual void printOut() = 0;
    static Base& getLower();
    };

    class Extended: public Base
    {
    public:
    void printOut() { cout << "hello"; }
    };

    Base& Base::getLower()
    {
    static Extended e;
    // Whatever code you were intending to have here, then:
    return e;
    }

    Note that with this scheme you always get the same object -- a singleton --
    from 'getLower'.

    Cheers & hth.,

    - Alf

    --
    blog at <url: http://alfps.wordpress.com>
     
    Alf P. Steinbach /Usenet, Nov 10, 2010
    #5
  6. Andrea Crotti

    Paul N Guest

    On Nov 10, 5:22 pm, Andrea Crotti <> wrote:
    > Ok apparently I got it, if I don't implement something it doesn't work
    >
    > With this is fine
    >     virtual void writeBuffer() {}
    >
    > With this stupid example I clarified my mind
    >
    > class Base
    > {
    > public:
    >     Base() {}
    >     virtual void printOut();
    >
    > };
    >
    > class Extended : public Base
    > {
    > public:
    >     Extended() {}
    >     void printOut() { cout << "hello"; }
    >
    > };
    >
    > (like this it doesn't work).
    >
    > Would be best to have
    >     virtual void writeBuffer() = 0
    >
    > to make it abstract, BUT then I have a static function that would
    > construct an object of subclass of Packet.  IF there is a pure function
    > in the class definition than I'm not allowed to return a Packet (even if
    > I know that it will be always a subclass of it).
    >
    > Now way to force the compiler about that?
    >
    > And also, why the hell just declaring it and implementing it in every
    > subclass doesn't work?
    > I mean the compiler should see it's actually implemented everywhere, so
    > what's the problem?


    I think part of the problem is that, if you want to return a Base by
    value, it has to actually be a Base and not an Extended. Likewise, if
    you want to pass it by reference it needs to really be of the type you
    say it is. However, and this may be what you're looking for, you can
    pass a *pointer* to a Base that actually points to an Extended. Then
    it doesn't matter whether you can actually create a Base or not.

    Paul.
     
    Paul N, Nov 10, 2010
    #6
  7. Andrea Crotti

    James Kanze Guest

    On Nov 10, 8:27 pm, "Alf P. Steinbach /Usenet"
    <> wrote:
    > * Andrea Crotti, on 10.11.2010 19:08:


    [...]
    > > Anyway I rephrase, first question is why this below doesn't find the
    > > reference to the vtable?


    > > class Base
    > > {
    > > public:
    > > virtual void printOut();
    > > };


    > > class Extended : public Base
    > > {
    > > public:
    > > void printOut() { cout<< "hello"; }
    > > };


    > > The only subclass actually implements the method I want, so
    > > should not that be enough? Or maybe it complains because
    > > the vtable is constructed at runtime (giving the possibility
    > > of bad crashes if nothing is found)?


    > The compiler doesn't know that you're not creating any pure
    > Base instances.


    Also, during the constructor and destructor of Base, the dynamic
    type is Base, and any calls to the virtual function go to
    Base::printOut.

    > And it doesn't care.


    > A virtual member function, except a pure virtual member
    > (that's a one with "= 0" at the end) must have an
    > implementation, so that the compiler can very mechanically put
    > the address of that implementation in the vtable, or use it in
    > whatever scheme it uses as an alternative to vtables.


    Yes. And if the dynamic resolution results in a call to a pure
    virtual function (e.g. because the call is made while in the
    constructor of Base), the behavior is undefined. Generally, the
    compiler will generate code which will cause the program to
    crash with an error message (although IIRC, early versions of
    g++ didn't have the error message, and some versions of VC++ do
    something else, and don't even crash).

    > > The second question was if it was possible to do something like


    > > class Extended;


    > > class Base
    > > {
    > > public:
    > > virtual void printOut() = 0;
    > > static Base getLower() {
    > > Extended e;
    > > return e;
    > > }
    > > };


    > > class Extended : public Base
    > > {
    > > public:
    > > void printOut() { cout<< "hello"; }
    > > };


    > > Apparently not if I understand, then I'll find some other ways..

    >
    > Problems with the above include


    > * 'getLower' attempts to return an object of abstract class.


    > * A local variable is declared with incomplete type 'Extended'.


    > * If those obstacles weren't in the way, 'getLower' would perform
    > a *slicing*, returning only the Base part of 'e', and then of type
    > 'Base'.


    > It's not clear what you're attempting, but it may be that you
    > want a Meyers' singleton:


    > class Base
    > {
    > public:
    > virtual void printOut() = 0;
    > static Base& getLower();
    > };


    > class Extended: public Base
    > {
    > public:
    > void printOut() { cout << "hello"; }
    > };


    > Base& Base::getLower()
    > {
    > static Extended e;
    > // Whatever code you were intending to have here, then:
    > return e;
    > }


    > Note that with this scheme you always get the same object --
    > a singleton -- from 'getLower'.


    Just for the record, that's *not* a Meyers' singleton, or any
    other type of singleton. (The first condition to be a singleton
    is that there is no way of getting more than one instance. In
    a Meyers' singleton, this is done by making the object
    noncopyable, and the constructor private. Which, of course,
    excludes derivation, unless you make the derived class
    a friend.)

    However, what you've just shown *is* the closest working
    approximation of what he seems to be trying to do. Unless he
    actually wants more than one instance---it's not really clear.
    For more than one instance, he'd need a factory function, e.g.

    class Base
    {
    public:
    virtual void printOut() = 0;
    static std::auto_ptr<Base> getLower();
    };

    class Extended: public Base
    {
    public:
    void printOut() { cout << "hello"; }
    };

    std::auto_ptr<Base> Base::getLower()
    {
    return std::auto_ptr<Base>( new Extended );
    }

    --
    James Kanze
     
    James Kanze, Nov 11, 2010
    #7
  8. Paul N <> writes:

    > I think part of the problem is that, if you want to return a Base by
    > value, it has to actually be a Base and not an Extended. Likewise, if
    > you want to pass it by reference it needs to really be of the type you
    > say it is. However, and this may be what you're looking for, you can
    > pass a *pointer* to a Base that actually points to an Extended. Then
    > it doesn't matter whether you can actually create a Base or not.
    >
    > Paul.


    I see, thanks, but if I want to follow the "standard" procedure passing
    a pointer already pointing to some allocated memory, I'm in the same
    problem again.

    Because I don't know what I should do outside of the function, if

    Packet *p = new <Beacon | Route> ...

    The only way then is to have the "new" inside this function, and then
    remember to free that memory again I guess...
     
    Andrea Crotti, Nov 11, 2010
    #8
  9. "Alf P. Steinbach /Usenet" <> writes:

    > Problems with the above include
    >
    > * 'getLower' attempts to return an object of abstract class.
    >
    > * A local variable is declared with incomplete type 'Extended'.


    What do you incomplete type?
    Because I had the forward declaration maybe?

    >
    > * If those obstacles weren't in the way, 'getLower' would perform
    > a *slicing*, returning only the Base part of 'e', and then of type
    > 'Base'.
    >
    > It's not clear what you're attempting, but it may be that you want a
    > Meyers' singleton:
    >
    > class Base
    > {
    > public:
    > virtual void printOut() = 0;
    > static Base& getLower();
    > };
    >
    > class Extended: public Base
    > {
    > public:
    > void printOut() { cout << "hello"; }
    > };
    >
    > Base& Base::getLower()
    > {
    > static Extended e;
    > // Whatever code you were intending to have here, then:
    > return e;
    > }
    >
    > Note that with this scheme you always get the same object -- a singleton --
    > from 'getLower'.
    >
    > Cheers & hth.,
    >
    > - Alf


    Anyway thanks but no, I don't think that's what I need, the simplest
    solution is just to avoid the pure function so I don't have an abstract
    class anymore and I can actually return something of that type.

    The other solution I guess is to use a pointer as Paul suggested.
    Thanks
     
    Andrea Crotti, Nov 11, 2010
    #9
  10. On Nov 11, 10:22 am, Andrea Crotti <> wrote:
    > "Alf P. Steinbach /Usenet" <> writes:
    >
    > > Problems with the above include

    >
    > >   * 'getLower' attempts to return an object of abstract class.

    >
    > >   * A local variable is declared with incomplete type 'Extended'.

    >
    > What do you incomplete type?
    > Because I had the forward declaration maybe?


    No, the type Extended was incomplete at the source-line
    Extended e;

    because only the forward declaration had been seen by the compiler and
    not yet the complete definition.
    A C++ compiler only does a very limited amount of look-ahead.
    Basically, the only things you can refer to, which come later in the
    source file, are members of a class while you are in the body of a
    member-function of that same class.

    >
    > >   * If those obstacles weren't in the way, 'getLower' would perform
    > >     a *slicing*, returning only the Base part of 'e', and then of type
    > >     'Base'.

    >
    > > It's not clear what you're attempting, but it may be that you want a
    > > Meyers' singleton:

    >
    > >   class Base
    > >   {
    > >   public:
    > >       virtual void printOut() = 0;
    > >       static Base& getLower();
    > >   };

    >
    > >   class Extended: public Base
    > >   {
    > >   public:
    > >       void printOut() { cout << "hello"; }
    > >   };

    >
    > >   Base& Base::getLower()
    > >   {
    > >       static Extended e;
    > >       // Whatever code you were intending to have here, then:
    > >       return e;
    > >   }

    >
    > > Note that with this scheme you always get the same object  --  a singleton  --
    > > from 'getLower'.

    >
    > > Cheers & hth.,

    >
    > > - Alf

    >
    > Anyway thanks but no, I don't think that's what I need, the simplest
    > solution is just to avoid the pure function so I don't have an abstract
    > class anymore and I can actually return something of that type.


    You should be careful with the possibility of slicing.
    This code

    #include <iostream>
    using namespace std;

    class Base
    {
    public:
    virtual void printOut() { cout<< "Base" << endl; }
    static Base getLower();
    };

    class Extended : public Base
    {
    public:
    void printOut() { cout<< "Extended" << endl; }
    };

    static Base Base::getLower() {
    Extended e;
    return e;
    }

    int main()
    {
    Base::getLower().printOut();
    }

    is guaranteed to always print "Base".
    The Base::getLower function returns an object of type Base, not of
    some derived type.

    >
    > The other solution I guess is to use a pointer as Paul suggested.
    > Thanks


    Or to use a smart pointer (like auto_ptr) as James suggested.

    Bart v Ingen Schenau
     
    Bart van Ingen Schenau, Nov 11, 2010
    #10
  11. James Kanze <> writes:
    >
    > Just for the record, that's *not* a Meyers' singleton, or any
    > other type of singleton. (The first condition to be a singleton
    > is that there is no way of getting more than one instance. In
    > a Meyers' singleton, this is done by making the object
    > noncopyable, and the constructor private. Which, of course,
    > excludes derivation, unless you make the derived class
    > a friend.)
    >
    > However, what you've just shown *is* the closest working
    > approximation of what he seems to be trying to do. Unless he
    > actually wants more than one instance---it's not really clear.
    > For more than one instance, he'd need a factory function, e.g.
    >
    > class Base
    > {
    > public:
    > virtual void printOut() = 0;
    > static std::auto_ptr<Base> getLower();
    > };
    >
    > class Extended: public Base
    > {
    > public:
    > void printOut() { cout << "hello"; }
    > };
    >
    > std::auto_ptr<Base> Base::getLower()
    > {
    > return std::auto_ptr<Base>( new Extended );
    > }
    >
    > --
    > James Kanze


    Ah nice I like this solution, so I can do something like

    auto_ptr<Base> Base::getLower() {
    auto_ptr<Base> val(new Extended);
    return val;
    }

    int main() {
    auto_ptr<Base> b = Base::getLower();
    b->printOut();
    delete b.release();
    return 0;
    }

    right?

    The delete if I got it it's not normally needed since when the auto_ptr
    goes out of scope the object pointed is delete automatically, right?
    Thanks
     
    Andrea Crotti, Nov 11, 2010
    #11
  12. * James Kanze, on 11.11.2010 10:16:
    > On Nov 10, 8:27 pm, "Alf P. Steinbach /Usenet"
    > <> wrote:
    >> * Andrea Crotti, on 10.11.2010 19:08:

    >
    > [...]
    >>> Anyway I rephrase, first question is why this below doesn't find the
    >>> reference to the vtable?

    >
    >>> class Base
    >>> {
    >>> public:
    >>> virtual void printOut();
    >>> };

    >
    >>> class Extended : public Base
    >>> {
    >>> public:
    >>> void printOut() { cout<< "hello"; }
    >>> };

    >
    >>> The only subclass actually implements the method I want, so
    >>> should not that be enough? Or maybe it complains because
    >>> the vtable is constructed at runtime (giving the possibility
    >>> of bad crashes if nothing is found)?

    >
    >> The compiler doesn't know that you're not creating any pure
    >> Base instances.

    >
    > Also, during the constructor and destructor of Base, the dynamic
    > type is Base, and any calls to the virtual function go to
    > Base::printOut.


    There are zillions of irrelevant details. Exactly why are you supplying this
    particular irrelevant detail?


    >> And it doesn't care.

    >
    >> A virtual member function, except a pure virtual member
    >> (that's a one with "= 0" at the end) must have an
    >> implementation, so that the compiler can very mechanically put
    >> the address of that implementation in the vtable, or use it in
    >> whatever scheme it uses as an alternative to vtables.

    >
    > Yes. And if the dynamic resolution results in a call to a pure
    > virtual function (e.g. because the call is made while in the
    > constructor of Base), the behavior is undefined. Generally, the
    > compiler will generate code which will cause the program to
    > crash with an error message (although IIRC, early versions of
    > g++ didn't have the error message, and some versions of VC++ do
    > something else, and don't even crash).


    The OP's code had no problem with calls of pure virtual functions.


    >>> The second question was if it was possible to do something like

    >
    >>> class Extended;

    >
    >>> class Base
    >>> {
    >>> public:
    >>> virtual void printOut() = 0;
    >>> static Base getLower() {
    >>> Extended e;
    >>> return e;
    >>> }
    >>> };

    >
    >>> class Extended : public Base
    >>> {
    >>> public:
    >>> void printOut() { cout<< "hello"; }
    >>> };

    >
    >>> Apparently not if I understand, then I'll find some other ways..

    >>
    >> Problems with the above include

    >
    >> * 'getLower' attempts to return an object of abstract class.

    >
    >> * A local variable is declared with incomplete type 'Extended'.

    >
    >> * If those obstacles weren't in the way, 'getLower' would perform
    >> a *slicing*, returning only the Base part of 'e', and then of type
    >> 'Base'.

    >
    >> It's not clear what you're attempting, but it may be that you
    >> want a Meyers' singleton:

    >
    >> class Base
    >> {
    >> public:
    >> virtual void printOut() = 0;
    >> static Base& getLower();
    >> };

    >
    >> class Extended: public Base
    >> {
    >> public:
    >> void printOut() { cout<< "hello"; }
    >> };

    >
    >> Base& Base::getLower()
    >> {
    >> static Extended e;
    >> // Whatever code you were intending to have here, then:
    >> return e;
    >> }

    >
    >> Note that with this scheme you always get the same object --
    >> a singleton -- from 'getLower'.

    >
    > Just for the record, that's *not* a Meyers' singleton, or any
    > other type of singleton.


    Sorry, it is a singleton, and it is a Meyers' singleton.

    There are many definitions of "singleton". Simplistic definitions (e.g.,
    Wikipedia's article on singletons) focus on a restriction to a single object, as
    you do, since that's common usage. What applies here is the more general concept
    of a globally single object that can only be accessed via a function and that is
    created on demand. For an example of a *slightly different more general
    meaning*, Python's True and False values are often described as singletons, of
    the 'bool' type, which has two singleton values -- note that that conflicts
    directly with your condition quoted below.

    The key feature of Meyers' singleton is that the object is created as a static
    local variable in the function.


    > (The first condition to be a singleton
    > is that there is no way of getting more than one instance. In
    > a Meyers' singleton, this is done by making the object
    > noncopyable, and the constructor private. Which, of course,
    > excludes derivation, unless you make the derived class
    > a friend.)


    Sorry again.

    First, as discussed above, the condition you state is not a condition of
    singletons in general (e.g., it conflicts directly with the common view of
    Python bool values as singletons), although such a restriction is often
    desirable and is often the reason for *using* a singleton.

    Secondly, in the OPs case those conditions will probably be satisfied anyway, by
    having Extended as a class defined in an implementation file.


    > However, what you've just shown *is* the closest working
    > approximation of what he seems to be trying to do. Unless he
    > actually wants more than one instance---it's not really clear.
    > For more than one instance, he'd need a factory function, e.g.
    >
    > class Base
    > {
    > public:
    > virtual void printOut() = 0;
    > static std::auto_ptr<Base> getLower();
    > };
    >
    > class Extended: public Base
    > {
    > public:
    > void printOut() { cout<< "hello"; }
    > };
    >
    > std::auto_ptr<Base> Base::getLower()
    > {
    > return std::auto_ptr<Base>( new Extended );
    > }


    Sorry, the simplest way and the practical way to support multiple instances is
    to expose class Extended to the client code.


    Cheers & hth.,

    - Alf

    --
    blog at <url: http://alfps.wordpress.com>
     
    Alf P. Steinbach /Usenet, Nov 11, 2010
    #12
  13. "Alf P. Steinbach /Usenet" <> writes:

    > Sorry, the simplest way and the practical way to support multiple
    > instances is to expose class Extended to the client code.
    >
    >
    > Cheers & hth.,
    >
    > - Alf


    I didn't get this sentence, what could be the alternative?
    I also tried to include the son class in the header and in the .cpp file
    but it still doesn't really work...

    at the moment the code is something like:
    auto_ptr<Packet> Packet::parseStream(const Stream& st)
    {
    Stream tmp = st;
    auto_ptr<Packet> res;
    FieldHeader fh(tmp.trim(FieldHeader::HEADER_SIZE));

    switch (fh.type) {
    case BEACON:
    res.reset(new Beacon);
    *res = Beacon::parseStream(tmp);
    break;
    }
    return res;
    }

    that reset maybe can be written in another way but for the rest I think
    it works well.
     
    Andrea Crotti, Nov 11, 2010
    #13
  14. Leigh Johnston <> writes:

    > On 11/11/2010 09:16, James Kanze wrote:
    >> However, what you've just shown *is* the closest working
    >> approximation of what he seems to be trying to do. Unless he
    >> actually wants more than one instance---it's not really clear.
    >> For more than one instance, he'd need a factory function, e.g.
    >>
    >> class Base
    >> {
    >> public:
    >> virtual void printOut() = 0;
    >> static std::auto_ptr<Base> getLower();
    >> };
    >>
    >> class Extended: public Base
    >> {
    >> public:
    >> void printOut() { cout<< "hello"; }
    >> };
    >>
    >> std::auto_ptr<Base> Base::getLower()
    >> {
    >> return std::auto_ptr<Base>( new Extended );
    >> }
    >>

    >
    > This is UB as Base does not contain a virtual destructor.
    >
    > /Leigh


    Can't find anywhere what "UB" mean, but I guess something bad...
    For understanding, why there should be a virtual destructor?

    And in general, whenever inside the classes I'm creating I don't
    allocate anything with "new", do I ever need a destructor?

    Or you mean that the virtual must be present since otherwise one
    subclass COULD have some memory leaks that could not be "closed" by the
    auto_ptr??
     
    Andrea Crotti, Nov 11, 2010
    #14
  15. * Andrea Crotti, on 11.11.2010 17:54:
    > "Alf P. Steinbach /Usenet"<> writes:
    >
    >> Sorry, the simplest way and the practical way to support multiple
    >> instances is to expose class Extended to the client code.
    >>
    >>
    >> Cheers& hth.,
    >>
    >> - Alf

    >
    > I didn't get this sentence, what could be the alternative?
    > I also tried to include the son class in the header and in the .cpp file
    > but it still doesn't really work...
    >
    > at the moment the code is something like:
    > auto_ptr<Packet> Packet::parseStream(const Stream& st)
    > {
    > Stream tmp = st;
    > auto_ptr<Packet> res;
    > FieldHeader fh(tmp.trim(FieldHeader::HEADER_SIZE));
    >
    > switch (fh.type) {
    > case BEACON:
    > res.reset(new Beacon);
    > *res = Beacon::parseStream(tmp);
    > break;
    > }
    > return res;
    > }
    >
    > that reset maybe can be written in another way but for the rest I think
    > it works well.


    The above changes the context of the discussion.

    The context of my remark was the earlier discussion, where there was a virtual
    member function 'getLower' with no arguments, producing a result of a fixed (but
    to client code unknown) type.

    In your new context you have a virtual member function 'parseStream' that
    produces a result of a type depending on the contents of a stream, i.e. not a
    fixed type.

    Don't expect an answer to a question A to necessarily apply to a in your view
    "similar" question B.

    Repeat: readers are not mind-readers.


    Cheers & hth.,

    - Alf

    --
    blog at <url: http://alfps.wordpress.com>
     
    Alf P. Steinbach /Usenet, Nov 11, 2010
    #15
  16. "Alf P. Steinbach /Usenet" <> writes:

    > The above changes the context of the discussion.
    >
    > The context of my remark was the earlier discussion, where there was a
    > virtual member function 'getLower' with no arguments, producing a
    > result of a fixed (but to client code unknown) type.
    >
    > In your new context you have a virtual member function 'parseStream'
    > that produces a result of a type depending on the contents of a
    > stream, i.e. not a fixed type.
    >
    > Don't expect an answer to a question A to necessarily apply to a in
    > your view "similar" question B.
    >
    > Repeat: readers are not mind-readers.
    >
    >
    > Cheers & hth.,
    >
    > - Alf


    Yes sure I wrote a simpler thing to show the problem and thought that it
    wasn't differing from the "original" problem, but in fact it does...

    Anyway thanks everyone problem solved :)
     
    Andrea Crotti, Nov 11, 2010
    #16
  17. Andrea Crotti

    James Kanze Guest

    On Nov 11, 10:58 am, Andrea Crotti <> wrote:
    > James Kanze <> writes:


    > > Just for the record, that's *not* a Meyers' singleton, or any
    > > other type of singleton. (The first condition to be a singleton
    > > is that there is no way of getting more than one instance. In
    > > a Meyers' singleton, this is done by making the object
    > > noncopyable, and the constructor private. Which, of course,
    > > excludes derivation, unless you make the derived class
    > > a friend.)


    > > However, what you've just shown *is* the closest working
    > > approximation of what he seems to be trying to do. Unless he
    > > actually wants more than one instance---it's not really clear.
    > > For more than one instance, he'd need a factory function, e.g.


    > > class Base
    > > {
    > > public:
    > > virtual void printOut() = 0;
    > > static std::auto_ptr<Base> getLower();
    > > };


    > > class Extended: public Base
    > > {
    > > public:
    > > void printOut() { cout << "hello"; }
    > > };


    > > std::auto_ptr<Base> Base::getLower()
    > > {
    > > return std::auto_ptr<Base>( new Extended );
    > > }


    > Ah nice I like this solution, so I can do something like


    > auto_ptr<Base> Base::getLower() {
    > auto_ptr<Base> val(new Extended);
    > return val;
    > }


    > int main() {
    > auto_ptr<Base> b = Base::getLower();
    > b->printOut();
    > delete b.release();
    > return 0;
    > }


    > right?


    > The delete if I got it it's not normally needed since when the
    > auto_ptr goes out of scope the object pointed is delete
    > automatically, right?


    Exactly.

    In a lot of shops, returning an std::auto_ptr is a convention
    for saying that you're transfering the responsibility of the
    delete. This is why boost::shared_ptr has a constructor which
    takes an auto_ptr, for example. It's a fairly good convention
    for objects which don't really manage themselves.

    --
    James Kanze
     
    James Kanze, Nov 11, 2010
    #17
  18. Andrea Crotti

    James Kanze Guest

    On Nov 11, 4:01 pm, "Alf P. Steinbach /Usenet" <alf.p.steinbach
    > wrote:
    > * James Kanze, on 11.11.2010 10:16:


    [...]
    > >> It's not clear what you're attempting, but it may be that you
    > >> want a Meyers' singleton:


    > >> class Base
    > >> {
    > >> public:
    > >> virtual void printOut() = 0;
    > >> static Base& getLower();
    > >> };


    > >> class Extended: public Base
    > >> {
    > >> public:
    > >> void printOut() { cout<< "hello"; }
    > >> };


    > >> Base& Base::getLower()
    > >> {
    > >> static Extended e;
    > >> // Whatever code you were intending to have here, then:
    > >> return e;
    > >> }


    > >> Note that with this scheme you always get the same object --
    > >> a singleton -- from 'getLower'.


    > > Just for the record, that's *not* a Meyers' singleton, or any
    > > other type of singleton.


    > Sorry, it is a singleton, and it is a Meyers' singleton.
    >
    > There are many definitions of "singleton".


    I'm using the one specified by the people who invented the
    pattern, the one documented in the GoF book, and the one which
    served as the basis of the name.

    > Simplistic definitions (e.g., Wikipedia's article on
    > singletons) focus on a restriction to a single object, as you
    > do, since that's common usage.


    And since that's what the design pattern was designed for.

    > What applies here is the more general concept of a globally
    > single object that can only be accessed via a function and
    > that is created on demand.


    Lazy construction. A concept which goes back even before
    singletons. With another name.

    > The key feature of Meyers' singleton is that the object is
    > created as a static local variable in the function.


    That is, in fact, the implementation detail which distinguishes
    Meyers' singleton from some other implementation.

    > First, as discussed above, the condition you state is not
    > a condition of singletons in general (e.g., it conflicts
    > directly with the common view of Python bool values as
    > singletons), although such a restriction is often desirable
    > and is often the reason for *using* a singleton.


    It is, in fact, the definition of "singleton".

    > Secondly, in the OPs case those conditions will probably be
    > satisfied anyway, by having Extended as a class defined in an
    > implementation file.


    > > However, what you've just shown *is* the closest working
    > > approximation of what he seems to be trying to do. Unless he
    > > actually wants more than one instance---it's not really clear.
    > > For more than one instance, he'd need a factory function, e.g.


    > > class Base
    > > {
    > > public:
    > > virtual void printOut() = 0;
    > > static std::auto_ptr<Base> getLower();
    > > };


    > > class Extended: public Base
    > > {
    > > public:
    > > void printOut() { cout<< "hello"; }
    > > };


    > > std::auto_ptr<Base> Base::getLower()
    > > {
    > > return std::auto_ptr<Base>( new Extended );
    > > }


    > Sorry, the simplest way and the practical way to support
    > multiple instances is to expose class Extended to the client
    > code.


    If that's what you want to do. If you don't, the factory
    function pattern, above, works quite well.

    --
    James Kanze
     
    James Kanze, Nov 11, 2010
    #18
  19. Andrea Crotti

    James Kanze Guest

    On Nov 11, 5:22 pm, Leigh Johnston <> wrote:
    > On 11/11/2010 16:58, Andrea Crotti wrote:
    > > Leigh Johnston<> writes:


    > >> On 11/11/2010 09:16, James Kanze wrote:
    > >>> However, what you've just shown *is* the closest working
    > >>> approximation of what he seems to be trying to do. Unless he
    > >>> actually wants more than one instance---it's not really clear.
    > >>> For more than one instance, he'd need a factory function, e.g.


    > >>> class Base
    > >>> {
    > >>> public:
    > >>> virtual void printOut() = 0;
    > >>> static std::auto_ptr<Base> getLower();
    > >>> };


    > >>> class Extended: public Base
    > >>> {
    > >>> public:
    > >>> void printOut() { cout<< "hello"; }
    > >>> };


    > >>> std::auto_ptr<Base> Base::getLower()
    > >>> {
    > >>> return std::auto_ptr<Base>( new Extended );
    > >>> }


    > >> This is UB as Base does not contain a virtual destructor.


    > > Can't find anywhere what "UB" mean, but I guess something bad...
    > > For understanding, why there should be a virtual destructor?


    > > And in general, whenever inside the classes I'm creating I don't
    > > allocate anything with "new", do I ever need a destructor?


    > > Or you mean that the virtual must be present since otherwise one
    > > subclass COULD have some memory leaks that could not be "closed" by the
    > > auto_ptr??


    > "UB" means "undefined behaviour". If deleting via a base class pointer
    > (which is what std::auto_ptr will do in Mr Kanze's example) the base
    > class must have a virtual destructor.


    > Yes, a memory leak could occur if the derived class allocated an object
    > as its destructor would not be called is the base class destructor was
    > not virtual.


    A memory leak could occur. Or the program could crash. Or it
    could just seem to work. You said it right the first time: it's
    undefined behavior. (FWIW, I've seen cases where it did crash.
    And others where it just corrupted the free space arena, causing
    a crash much later. Both involved multiple inheritance, but the
    principle is there.)

    --
    James Kanze
     
    James Kanze, Nov 11, 2010
    #19
  20. * James Kanze, on 11.11.2010 19:34:
    > On Nov 11, 4:01 pm, "Alf P. Steinbach /Usenet"<alf.p.steinbach
    > > wrote:
    >> * James Kanze, on 11.11.2010 10:16:

    >
    > [...]
    >>>> It's not clear what you're attempting, but it may be that you
    >>>> want a Meyers' singleton:

    >
    >>>> class Base
    >>>> {
    >>>> public:
    >>>> virtual void printOut() = 0;
    >>>> static Base& getLower();
    >>>> };

    >
    >>>> class Extended: public Base
    >>>> {
    >>>> public:
    >>>> void printOut() { cout<< "hello"; }
    >>>> };

    >
    >>>> Base& Base::getLower()
    >>>> {
    >>>> static Extended e;
    >>>> // Whatever code you were intending to have here, then:
    >>>> return e;
    >>>> }

    >
    >>>> Note that with this scheme you always get the same object --
    >>>> a singleton -- from 'getLower'.

    >
    >>> Just for the record, that's *not* a Meyers' singleton, or any
    >>> other type of singleton.

    >
    >> Sorry, it is a singleton, and it is a Meyers' singleton.
    >>
    >> There are many definitions of "singleton".

    >
    > I'm using the one specified by the people who invented the
    > pattern, the one documented in the GoF book, and the one which
    > served as the basis of the name.


    Well, you're quibbling about terminology, not realizing that "vehicle" can mean
    something more general than a Mazda RX7.

    Now, I gave you some pointers, including usage in direct conflict with your POV.

    You should have been able to gain an understanding from that.

    If not, then sorry, can't help.

    By the way, I sincerely doubt that you do know who invented singletons. I'm
    treating that comment as arm-waving trying to implant the notion of you having a
    very intimate knowledge of the early history of singletons. Which, even you were
    an expert in the early history of singletons (a very peculiar interest, but then
    so are some hobbies), would be totally irrelevant to modern usage.


    >> Simplistic definitions (e.g., Wikipedia's article on
    >> singletons) focus on a restriction to a single object, as you
    >> do, since that's common usage.

    >
    > And since that's what the design pattern was designed for.
    >
    >> What applies here is the more general concept of a globally
    >> single object that can only be accessed via a function and
    >> that is created on demand.

    >
    > Lazy construction. A concept which goes back even before
    > singletons. With another name.


    Sorry, no, lazy construction is involved in that meaning of singleton, but lazy
    construction is a term or description that also applies to many other situations.


    Cheers & hth.,

    - Alf

    --
    blog at <url: http://alfps.wordpress.com>
     
    Alf P. Steinbach /Usenet, Nov 11, 2010
    #20
    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. Felipe
    Replies:
    3
    Views:
    445
    Felipe
    Jul 16, 2004
  2. Lu
    Replies:
    1
    Views:
    576
    Roel Schroeven
    Jul 10, 2003
  3. Mantorok Redgormor
    Replies:
    70
    Views:
    1,762
    Dan Pop
    Feb 17, 2004
  4. VK
    Replies:
    45
    Views:
    602
    Dr John Stockton
    Sep 12, 2006
  5. -Lost
    Replies:
    13
    Views:
    372
    Richard Cornford
    Jan 31, 2007
Loading...

Share This Page