CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 18
  1. #1
    Join Date
    Jun 2009
    Posts
    17

    Question Constructor to extend existing class

    I would like to extend the ANSI string class to include rudimentary split and join functions. I am NOT adding any new data fields to string:

    class string_sj : public string {

    public:

    ...

    }

    I would like to be able to use constructs such as

    void arbitrary_function(string & s)
    {
    string_sj myString = s;

    // or

    string_sj *pMyString = new string_sj(s);
    }

    How do I add a constructor to class string_sj to allow this? I've tried

    public:
    string_sj(string & s) { string(s); }

    and variation of this, but the compiler says: "redefinition of formal parameter 's' "

    I have also tried

    class string_sj : public string, string(string &) { ... }

    but the compiler doesn't like that either.

    I remember this topic being covered in the C++ class I took years ago, but I can't remember how to do it today.

    K.

  2. #2
    Join Date
    Nov 2006
    Location
    Essen, Germany
    Posts
    1,344

    Re: Constructor to extend existing class

    That´s probably a bad idea since std::string´s destructor isn´t virtual and therefore std::string isn´t supposed to derive from.
    Splitting/joining strings are operations that can be achieved by using std::string´s public interface, so why don´t you solve the task by implement non member functions?
    - Guido

  3. #3
    Join Date
    Jun 2009
    Posts
    17

    Re: Constructor to extend existing class

    Thanks for your suggestion on the specifics of extending string (and why it's a bad idea). I will consider your suggestion seriously.

    On the more general problem of extending constructors, after doing some google searches, I found the following construct, which the compiler does accept:

    class string_sj : public string {

    public:
    string_sj(string & s) : string(s) { }

    ...

    };

    This does ring a bell from what I learned (and forgot) in that class. I think this accomplishes what I intend (and is applicable to extending other classes where I'm only adding new methods).

    K.

  4. #4
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: Constructor to extend existing class

    Yes, you are looking at a constructor initialisation list, which can be used to initialise base class subobjects.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  5. #5
    Join Date
    Apr 2004
    Location
    Canada
    Posts
    1,342

    Re: Constructor to extend existing class

    Quote Originally Posted by GNiewerth View Post
    That´s probably a bad idea since std::string´s destructor isn´t virtual and therefore std::string isn´t supposed to derive from.
    This is something I hear over and over again, but I could never quite grasp what's so wrong about it. Yes, I understand why virtual destructors are necessary and why it's generally a bad idea to derive from a class with a non-virtual destructor, but:

    • The only time not having a virtual destructor is relevant is when you try to delete a pointer to a base class which really points to a derived class object - in other words, when you're using the hierarchy polymorphically. Usually, including this time, the reason for deriving from std::string is to extend its functionality by adding member functions. I cannot conceive of a scenario where the resulting hierarchy would be used polymorphically - we generally don't even allocate string objects using new (other than implicitly, e.g. inside a vector<string>, but that's not a problem). Seriously, what design would possibly require something along the lines of a vector<string*> where some of the pointers point to std::string objects and some point to objects of the derived class?
    • Even if we did attempt to use the hierarchy polymorphically, all that would happen is the destructor of the derived class would not be invoked. Is this a problem if the destructor of the derived class would be a no-op anyways (e.g. if no new data members were added to the derived class, only new methods)?
    Old Unix programmers never die, they just mv to /dev/null

  6. #6
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: Constructor to extend existing class

    Quote Originally Posted by HighCommander4
    I cannot conceive of a scenario where the resulting hierarchy would be used polymorphically
    Indeed, so it would make more sense to either use composition or private inheritance, in which case this lack of a virtual destructor would no longer be a (potential) problem. (Of course, one can also use polymorphism without destroying derived class objects through base class pointers).

    Quote Originally Posted by HighCommander4
    Even if we did attempt to use the hierarchy polymorphically, all that would happen is the destructor of the derived class would not be invoked. Is this a problem if the destructor of the derived class would be a no-op anyways (e.g. if no new data members were added to the derived class, only new methods)?
    In practice, probably not. But strictly speaking, the behaviour is undefined, and in practice it is feasible for conditions to change under maintenance.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  7. #7
    Join Date
    Apr 2004
    Location
    Canada
    Posts
    1,342

    Re: Constructor to extend existing class

    Quote Originally Posted by laserlight View Post
    Indeed, so it would make more sense to either use composition or private inheritance, in which case this lack of a virtual destructor would no longer be a (potential) problem.
    If your objective is to extend the std::string class with a few methods of your own, then using composition or private inheritance would be counterproductive because you'd need to write wrappers for all the existing methods of std::string.
    Old Unix programmers never die, they just mv to /dev/null

  8. #8
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: Constructor to extend existing class

    Quote Originally Posted by HighCommander4
    If your objective is to extend the std::string class with a few methods of your own, then using composition or private inheritance would be counterproductive because you'd need to write wrappers for all the existing methods of std::string.
    "If your objective is to extend the std::string class with a few methods of your own", then provide non-member functions that do that.

    If you are going to add data members, then you are on your way to some specialised string class, so using composition or private inheritance and only forwarding (or using using declarations) relevant member functions makes sense.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  9. #9
    Join Date
    Apr 2004
    Location
    Canada
    Posts
    1,342

    Re: Constructor to extend existing class

    Quote Originally Posted by laserlight View Post
    "If your objective is to extend the std::string class with a few methods of your own", then provide non-member functions that do that.
    What if I want to avoid polluting a namespace with generic-looking function names like join() or trim() which may already be used for other things?
    Old Unix programmers never die, they just mv to /dev/null

  10. #10
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: Constructor to extend existing class

    Quote Originally Posted by HighCommander4
    What if I want to avoid polluting a namespace with generic-looking function names like join() or trim() which may already be used for other things?
    Create another namespace.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  11. #11
    Join Date
    Apr 2004
    Location
    Canada
    Posts
    1,342

    Re: Constructor to extend existing class

    Quote Originally Posted by laserlight View Post
    Create another namespace.
    So now users of my string class, need to put not only
    Code:
    using std::string;
    but also
    Code:
    using my_namespace::join;
    using my_namespace::trim;
    at the top of their files - that's assuming they're not already using join() or trim() functions from other namespaces. If they are, they now need to qualify explicitly every invocation:
    Code:
    string s;
    ...
    my_namespace::trim(s);
    as compared to
    Code:
    better_string s;
    ...
    s.trim();
    Old Unix programmers never die, they just mv to /dev/null

  12. #12
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: Constructor to extend existing class

    Quote Originally Posted by HighCommander4
    that's assuming they're not already using join() or trim() functions from other namespaces. If they are, they now need to qualify explicitly every invocation:
    So? This is the very point of having namespaces in the first place: you can use using declarations and using directives where it is convenient, and fully qualify to disambiguate where necessary.

    On a related note, you might want to read Sutter's article GotW #84: Monoliths "Unstrung" and an interview of Stroustrup where he discusses about Designing Simple Interfaces. Sutter's article references Meyers' article on How Non-Member Functions Improve Encapsulation.

    EDIT:
    Oh, and besides the choice of using declarations/directives and qualification with the given namespace name, the user can also alias the namespace name and use that to qualify the names in the namespace.
    Last edited by laserlight; June 22nd, 2009 at 03:53 PM.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  13. #13
    Join Date
    Nov 2006
    Posts
    1,611

    Re: Constructor to extend existing class

    A few things occurred to me as a read through this thread.

    I've had a number of encounters with the notion that a derived class may not require a virtual destructor, and experiment does seem to confirm this viewpoint on a great many compilers. There are a number of tempting arguments to promote the reasoning, but there are complications.

    Like so many other arguments of this kind, the merits and demerits of goto being an example in a current thread of discussion hear, it's long winded, but not quite as controversial. The matter is eventually settled, and laserlight has the point. Even though it appears to work, it is specifically 'marked' as undefined behavior, and that alone should be sufficient to deter it as a practice. There are more, though, perhaps more convincing. There's little way to guarantee the class we create on this assumption retains that assumption when the code changes hands, even our own future hands should we forget or skip the documentation "beyond this place there be dragons". Someone might add data to the class, forgetting that it may not be destroyed appropriately.

    Another point, almost as convincing, is what happens when the proposed derived class would be used as a parameter to a function expecting a string, either of a string *, string & or string by value. It's not so much what happens to slice off the derived class (if it has no data, where' not loosing much), but what if the purpose will eventually be to get it back.

    In other words, do we not expect to get a string FROM something which we would hope to treat or use as this derived string object? If true (and we know it could be under a wide variety of circumstances), how? Insisting on placing the functional extension in a derived class actually causes a problem at this point.

    Moving the functionality into a set of non-member functions steps aside these issues, and they have the potential to benefit a lot more of our code than the perception of namespace complications.

    Laserlight has some good references on these points - objects (that somewhat vaguely defined term) need not be defined only by member functions, but a family of functions acting upon a concept - wherever those functions are placed. In particular, the point that we may obtain a string object from sources outside OUR code for which we want these new features I think is the paramount issue; as non-member functions their use is more widely usable in a situation like this (extending an existing library).

    But a composition approach need not be all that bad. The class could accept a string as a reference upon construction and when required provide an automatic conversion to string so it could still be used as a string when required. When you consider that the new behaviors are likely to be needed only on occasion, this is likely a comfortable solution.
    Last edited by JVene; June 22nd, 2009 at 10:50 PM.
    If my post was interesting or helpful, perhaps you would consider clicking the 'rate this post' to let me know (middle icon of the group in the upper right of the post).

  14. #14
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: Constructor to extend existing class

    To bring this back full circle to the scenario that led to the original question...
    Quote Originally Posted by kahahn
    I would like to extend the ANSI string class to include rudimentary split and join functions.
    Consider using the Boost.StringAlgo library instead of writing your own functions.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  15. #15
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Constructor to extend existing class

    Adding 'useful' functionality to a class, whether by inheritance or composition always sounds like a great idea at first, but I know from experience that it can lead to bloated and inflexible classes.

    My own experience came from creating a set of image classes many years ago; 8bit grey, 16bit grey, 8 bit RBG. Over the years, various coders added functionality to the various image classes (not always consistently), all of which were 'obviously' part of the image API. After a few years the classes had grown a large set of miscellaneous functions, not all implemented in each image class, not all useful in every application.

    In the end we wiped the slate clean and started from an STL perspective and redesigned a set of templated classes and functions that separated images from algorithms.
    Now the image classes are much easier to maintain (virtually nothing needs to be done to them now) and the algorithms are separate entities, only loosely coupled to the images (though iterators), and by way of templates, applicable to all image classes.
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured