-
June 28th, 2012, 04:59 PM
#1
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.
-
June 28th, 2012, 06:50 PM
#2
Re: pimpl class with pointer to base class
Originally Posted by treuss
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.
Originally Posted by treuss
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
-
June 29th, 2012, 02:02 AM
#3
Re: pimpl class with pointer to base class
Originally Posted by D_Drmmr
You didn't implement the assignment operator for the Wrapper class.
D'oh! Knew it was something stupidly simple.
Originally Posted by D_Drmmr
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.
-
June 29th, 2012, 02:59 AM
#4
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|