CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4
  1. #1
    Join Date
    Jan 2004
    Location
    Düsseldorf, Germany
    Posts
    2,401

    pimpl class with pointer to base class

    I'm trying to implement a class hierarchy and a wrapper class with a pointer to the base class. The base class has operator< overloaded and the implementation makes use of virtual functions as some of the logic for sorting is in the derived classes. Unfortunately, when trying to use the base class operator< from the wrapper, I get a "pure virtual method called".

    Below code is meant to illustrate my problem. Unfortunately it crashes on me (upon destruction of vec) and I cannot quite see, why. So two questions:

    1. Can somebody spot the error I made in the code below (having lived in Java-land for the last 5 years, I'm sure I just did some stupid error)?
    2. How can I implement Wrapper::operator< to use Base::operator<? I know I could write a function and pass it to sort but I'm interessted if there is a way to actually use Base::operator<.

    Code:
    #include <vector>
    #include <algorithm>
    #include <cmath>
    
    class Base {
    public:
      virtual ~Base() {}
      virtual int getValue() const = 0;
      virtual Base * clone() const = 0;
      bool operator<(const Base& rhs) const {
        return getValue() < rhs.getValue();
      }
    };
    
    class Derived : public Base {
    private:
      int value_;
    public:
      Derived() : value_(rand()) {}
      Derived(const Derived& rhs) : value_(rhs.value_) {}
      virtual Derived * clone() const { return new Derived(*this); }
      virtual int getValue() const { return value_; };
    };
    
    class Wrapper
    {
    private:
      Base * pimpl_;
    public:
      Wrapper() : pimpl_(new Derived()) {}
      Wrapper(const Wrapper& rhs) : pimpl_(rhs.pimpl_->clone()) {}
      ~Wrapper() { delete pimpl_; }
      bool operator<(const Wrapper& rhs) const {
        return pimpl_->getValue() < rhs.pimpl_->getValue();
      }
    };
    
    
    using namespace std;
    
    int main() {
      vector<Wrapper> vec(10);
      sort(vec.begin(), vec.end());
    }
    Thanks everybody.

    PS: Anybody else hates the new design?
    Last edited by treuss; June 28th, 2012 at 05:00 PM. Reason: Disabled smilieys
    More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason - including blind stupidity. --W.A.Wulf

    Premature optimization is the root of all evil --Donald E. Knuth


    Please read Information on posting before posting, especially the info on using [code] tags.

  2. #2
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: pimpl class with pointer to base class

    Quote Originally Posted by treuss View Post
    1. Can somebody spot the error I made in the code below (having lived in Java-land for the last 5 years, I'm sure I just did some stupid error)?
    You didn't implement the assignment operator for the Wrapper class.
    Quote Originally Posted by treuss View Post
    2. How can I implement Wrapper::operator< to use Base::operator<? I know I could write a function and pass it to sort but I'm interessted if there is a way to actually use Base::operator<.
    Code:
      bool operator<(const Wrapper& rhs) const {
        return *pimpl_ < *rhs.pimpl_;
      }
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  3. #3
    Join Date
    Jan 2004
    Location
    Düsseldorf, Germany
    Posts
    2,401

    Re: pimpl class with pointer to base class

    Quote Originally Posted by D_Drmmr View Post
    You didn't implement the assignment operator for the Wrapper class.
    D'oh! Knew it was something stupidly simple.

    Quote Originally Posted by D_Drmmr View Post
    Code:
      bool operator<(const Wrapper& rhs) const {
        return *pimpl_ < *rhs.pimpl_;
      }
    Hmm, that's what I assumed and tried but it gave me "the pure virtual method called" error, so I thought I was truncating the derived classes to their base classes. Apparently not though, as it works fine with the test program. Need to check what I did wrong.

    Thanks for the help!
    Last edited by treuss; June 29th, 2012 at 02:03 AM. Reason: Spelling
    More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason - including blind stupidity. --W.A.Wulf

    Premature optimization is the root of all evil --Donald E. Knuth


    Please read Information on posting before posting, especially the info on using [code] tags.

  4. #4
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: pimpl class with pointer to base class

    If you have access to it, I'd suggest you define your pimpl_ as type std::unique_ptr<Base>. Ditto for clone.

    This could help you in a different places:
    1) Clone never leaks.
    2) Wrapper class would not have been able to define the operator= you had forgotten to define youself.
    3) default destructor works.

    Finally, the potentially non-trivial implementation of operator= (if you want one with strong exception safety) becomes easy as pie:

    Code:
    Wrapper& operator=(const Wrapper& rhs)
    {
      pimpl_ = rhs.pimpl_->clone();
      return *this;
    }
    Here, if clone throws, you this object is not yet modified. If it succeeds, the std::unique_ptr:perator= will be the one responsible for the clean up of its own internals. Awesome. Overall, I don't think you could shoot yourself if you tried.

    It is a bit of overhead, but I think the extra safety is well worth it.
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

Tags for this Thread

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