I'm deriving from a base class in a library, and the library vendor is
expecting me to add a 'string&' member in my derived class. Or, to be
more precise, they have provided two virtual functions:
1 void setstr(const std::string& str)
2 std::string& getstr(void)
So my obvious implementation is:
class foo : vendor_bar {
string& str;
public:
virtual void setstr(const string& str_) { str = str_; }
virtual string& getstr(void) { return str; }
};
I've got a bad feeling about this. Is it a good idea to have a
reference member like this? I can't think of any specific problems,
but I'd rather use a smart pointer of some sort.
Another factor is that the string is actually originally provided by
me (the library user), isn't used elsewhere in the library, and simply
comes back to me in the 'setstr' call; I use it myself further down in
the hierarchy. Given this, is there some better way that the library
could have been designed, rather than hard-wiring in a string
implementation?
Cheers
AL 13 1086
* Andy Lomax: I'm deriving from a base class in a library, and the library vendor is expecting me to add a 'string&' member in my derived class. Or, to be more precise, they have provided two virtual functions:
1 void setstr(const std::string& str) 2 std::string& getstr(void)
Bad design.
So my obvious implementation is:
class foo : vendor_bar { string& str; public: virtual void setstr(const string& str_) { str = str_; } virtual string& getstr(void) { return str; } };
Change that member declaration to just
string str;
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
On Fri, 24 Jun 2005 10:07:50 GMT, al***@start.no (Alf P. Steinbach)
wrote: * Andy Lomax: I'm deriving from a base class in a library, and the library vendor is expecting me to add a 'string&' member in my derived class. Or, to be more precise, they have provided two virtual functions:
1 void setstr(const std::string& str) 2 std::string& getstr(void)
Bad design.
Do you have any specific reasons for saying that it's bad? So my obvious implementation is:
class foo : vendor_bar { string& str; public: virtual void setstr(const string& str_) { str = str_; } virtual string& getstr(void) { return str; } };
Change that member declaration to just
string str;
Hmm... problem is, this class may be instantiated thousands of times,
all containing exactly the same string. Any other ideas?
Thanks -
AL
"Andy Lomax" <ab***@[127.0.0.1]> wrote in message
news:ea********************************@4ax.com On Fri, 24 Jun 2005 10:07:50 GMT, al***@start.no (Alf P. Steinbach) wrote:
* Andy Lomax: I'm deriving from a base class in a library, and the library vendor is expecting me to add a 'string&' member in my derived class. Or, to be more precise, they have provided two virtual functions:
1 void setstr(const std::string& str) 2 std::string& getstr(void)
Bad design.
Do you have any specific reasons for saying that it's bad?
So my obvious implementation is:
class foo : vendor_bar { string& str; public: virtual void setstr(const string& str_) { str = str_; } virtual string& getstr(void) { return str; } };
Change that member declaration to just
string str;
Hmm... problem is, this class may be instantiated thousands of times, all containing exactly the same string. Any other ideas?
If you only want one string for the whole class, then the obvious thing to
do is make it a static member.
--
John Carson
On Fri, 24 Jun 2005 22:10:22 +1000, "John Carson"
<jc****************@netspace.net.au> wrote: If you only want one string for the whole class, then the obvious thing to do is make it a static member.
Sorry, not making myself clear. The class may be instantiated
thousands of times, but there may be only 4 or 5 unique values for the
string; I can't tell before runtime.
Ideally, I'd like to declare a smart pointer, but I can't see how to
tie that in with the prototypes that the library vendor has given me.
I can create a smart ptr for the string when I first create the
string, before passing it into the library as a reference. However,
when the library eventually calls 'setstr' with this reference, I
can't turn it back into the original smart ptr without some sort of
search.
Cheers
AL
> I'm deriving from a base class in a library, and the library vendor is expecting me to add a 'string&' member in my derived class. Or, to be more precise, they have provided two virtual functions:
1 void setstr(const std::string& str) 2 std::string& getstr(void)
Bad design.
These are NOT badly designed methods. They are, in fact, recommended.
Rather than rant on why, I'll point you to Herb Sutter's "Exceptional
C++" series.
I DO agree, however, that you just want to declare for your member:
string str;
The reason is that you'll be taking, in the case of the setter, a const
reference. The strings copy contructor will not be called and will
therefore cause undue overhead during the assignment operation.
Likewise for the getter; you'll return a reference (maybe should be a
const ref) and avoid copy contruction on the return from the method.
That should have read, "not cause undue overhead." I apologize for the
confusion.
Andy Lomax wrote: I'm deriving from a base class in a library, and the library vendor is expecting me to add a 'string&' member in my derived class. Or, to be more precise, they have provided two virtual functions:
1 void setstr(const std::string& str) 2 std::string& getstr(void)
So my obvious implementation is:
class foo : vendor_bar { string& str; public: virtual void setstr(const string& str_) { str = str_; } virtual string& getstr(void) { return str; } };
This shouldnt even compile! What does 'str' refer to?
You're absolutely correct -- if you assume that the constructor didn't
assign (and take) a std::string& for an argument. It will compile,
however, if the class is defined like so:
....
class SomeStrClass
{
private:
std::string& m_str;
public:
SomeStrClass(std::string& init_str)
: m_str(init_str)
{
}
~SomeStrClass(void)
{
}
void set_str(const std::string& str)
{
m_str = str;
}
const std::string& get_str(void) const
{
return m_str;
}
};
Note that changing the constructor to the following will NOT work:
SomeStrClass(void)
: m_str("")
{
}
The reason (if its not obvious) is that you cannot assign a reference
to a temporary. You'd end up with a "what does this string refer to"
type situation like your question asks.
On 24 Jun 2005 07:25:06 -0700, "Shaun" <se******@gvtc.com> wrote: Bad design.
These are NOT badly designed methods. They are, in fact, recommended. Rather than rant on why, I'll point you to Herb Sutter's "Exceptional C++" series.
Already got 6 C++ and STL books, with a 7th in the post, so I'm afraid
I'll have to pass up on that. It'll take me to the next ice age just
to read this lot.
I don't suppose you could summarise? :)
Cheers
AL
"Andy Lomax" <ab***@[127.0.0.1]> wrote in message
news:8b********************************@4ax.com On Fri, 24 Jun 2005 22:10:22 +1000, "John Carson" <jc****************@netspace.net.au> wrote:
If you only want one string for the whole class, then the obvious thing to do is make it a static member.
Sorry, not making myself clear. The class may be instantiated thousands of times, but there may be only 4 or 5 unique values for the string; I can't tell before runtime.
Ideally, I'd like to declare a smart pointer, but I can't see how to tie that in with the prototypes that the library vendor has given me. I can create a smart ptr for the string when I first create the string, before passing it into the library as a reference. However, when the library eventually calls 'setstr' with this reference, I can't turn it back into the original smart ptr without some sort of search.
I don't know what the smartness of the pointer has to do with anything.
If you think it is worth the trouble (which seems doubtful to me), it seems
that what you need is an auxiliary structure (say, a set since you can
insert without invalidating addresses). You make the set a static member of
the class and each object of the class has a pointer to an entry in this
set. Try the following:
#include<string>
#include<set>
#include <iostream>
using namespace std;
class vendor_bar
{};
class foo : vendor_bar {
string* pstr;
static set<string> s;
public:
virtual void setstr(const string& str_)
{ pstr = &(*s.insert(str_).first); }
virtual string& getstr(void) { return *pstr; }
};
set<string> foo::s;
// Note that, rather helpfully, set::insert will only make
// an actual insertion if the string isn't already there.
// If it is there, it just returns an iterator to the existing element.
int main()
{
const int number=8;
foo f[number];
f[0].setstr("First");
f[1].setstr("First");
f[2].setstr("Second");
f[3].setstr("Second");
f[4].setstr("Third");
f[5].setstr("Fourth");
f[6].setstr("Fifth");
f[7].setstr("Fifth");
for(int i=0; i<number; ++i)
cout << "i: " << i << " string is: " << f[i].getstr() << endl;
}
You could further complicate this by refcounting the entries in the set and
removing an entry when no object stored its address, but this seems unlikely
to be worth it.
--
John Carson
Thanks - I'll check the references. I think your other reference was
probably Meyer #20 - 'Prefer pass-by-reference-to-const to
pass-by-value'; I found that this morning.
Cheers
AL
* Shaun: "I don't suppose you could summarise?"
Now that I think of it it may be Scott Meyers book, "Effective C++" (if not both books), however the guidline is generally stated as follows:
"prefer pass-by-reference to pass-by-value"
you can pair this with another oft-stated guidline, "use const whenever possible".
You remember the first one incorrectly (unless Scott Meyers has written in
his sleep); the second is advice I've given myself, publicly.
Anyway it doesn't have anything to do with the interface Andy was given:
void setstr(const std::string& str)
std::string& getstr(void)
It's badly designed, period.
It also indicates that the person writing it is more familiar with C than
C++.
The only way it could make sense would be for 'getstr' to return a reference
to a non-per-instance member, e.g. a static member or global.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail? This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: wired |
last post by:
Hi,
I've just taught myself C++, so I haven't learnt much about style or
the like from any single source, and I'm quite styleless as a result.
But at the same time, I really want nice code and I...
|
by: Steven T. Hatton |
last post by:
The code shown below is an example from the Coin3D documentation. I believe
the use of the C-style cast is safe under the circumstances, but from what
I've been exposed to (TC++PL(SE)), I would...
|
by: Cameron Hatfield |
last post by:
I was wondering how good this page of coding standards
(http://www.doc.ic.ac.uk/lab/cplus/c++.rules/) is.
Is it too outdated?
|
by: Ruben Van Havermaet |
last post by:
Hi,
I have a problem using member functions in derived classes that
override virtual member functions of base classes.
The following pieces of (simplified) code don't work. Can anybody give...
|
by: Mark Sisson |
last post by:
Hi all.
SITUATION
================
1. I have a base class with a member variable that's an object
2. I have several classes that inherit from the base class.
3. There are several methods in...
|
by: Bill Rubin |
last post by:
The following code snippet shows that VC++ 7.1 correctly compiles a static member function invocation from an Unrelated class, since this static member function is public. I expected to compile the...
|
by: Wayne Brantley |
last post by:
VS2005 RTM
Create a web user control to use as a base class for other web user
controls.
Now, create a new web user control, change the class it inherits from to
your base class and compile....
|
by: Valeriu Catina |
last post by:
Hi,
consider the Shape class from the FAQ:
class Shape{
public:
Shape();
virtual ~Shape();
virtual void draw() = 0;
|
by: Bob Johnson |
last post by:
I have a base class that must have a member variable populated by, and only
by, derived classes.
It appears that if I declare the variable as "internal protected" then the
base class *can*...
|
by: ryjfgjl |
last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
|
by: emmanuelkatto |
last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud.
Please let me know.
Thanks!
Emmanuel
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: Sonnysonu |
last post by:
This is the data of csv file
1 2 3
1 2 3
1 2 3
1 2 3
2 3
2 3
3
the lengths should be different i have to store the data by column-wise with in the specific length.
suppose the i have to...
|
by: Hystou |
last post by:
There are some requirements for setting up RAID:
1. The motherboard and BIOS support RAID configuration.
2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers,...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
|
by: agi2029 |
last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
| |