469,926 Members | 1,489 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,926 developers. It's quick & easy.

why won't this complile??? const troubles...

this doesn't want to compile....

class image : public std::list<element>
{
element getElement(key k) const
{
image::iterator iter;
for (iter=begin(); iter != end(); ++iter)
{
element &elem(*iter);
if (Key == k)
{
return(elem);
}
}
throw("Not found");
}
};

I think the reason this isn't working is due to the const declaration of
the
method.
So what am I to do?

Jul 22 '05 #1
15 1507
JustSomeGuy wrote:
this doesn't want to compile....
Always post the full error message.
class image : public std::list<element>
{
element getElement(key k) const
{
image::iterator iter;
for (iter=begin(); iter != end(); ++iter)
{
element &elem(*iter);
if (Key == k)
{
return(elem);
}
}
throw("Not found");
}
};

I think the reason this isn't working is due to the const declaration
of the method.


It is due to you trying to use a non-const-iterator on a const
container. Use const_iterator instead of iterator.

Jul 22 '05 #2
JustSomeGuy wrote:
this doesn't want to compile....

class image : public std::list<element>
{
element getElement(key k) const
{
image::iterator iter;
for (iter=begin(); iter != end(); ++iter)
{
element &elem(*iter);
if (Key == k)
{
return(elem);
}
}
throw("Not found");
}
};

I think the reason this isn't working is due to the const declaration of
the
method.
So what am I to do?


Don't inherit std::list<>.

Generally, only inherit to override a virtual method. STL does not use any
virtuals.

If many clients used the image class, they might start playing with all the
different functions which std::list<> provides. When the time came to
replace the list with something else, those clients would resist that
change. Library classes, such as std::list<>, should have very wide
interfaces, but application-specific classes must be very narrow.

BTW the actual fix is image::const_iterator.

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces


Jul 22 '05 #3
Phlip wrote:
Don't inherit std::list<>.

Generally, only inherit to override a virtual method. STL does not use any
virtuals.


Earlier I asked a question about inheriting std::priority_queue<>. It
seems that priority_queue is designed to be inherited (as it has
protected members), even though it has no virtuals.

There are many reasons to inherit, even if something has no virtuals,
such as adding new behavior, even though it doesn't modify existing
(Note that I was using private inheritance).

Blanket bans may not be a good thing.
Jul 22 '05 #4
Rolf Magnus wrote:
JustSomeGuy wrote:
this doesn't want to compile....


Always post the full error message.
class image : public std::list<element>
{
element getElement(key k) const
{
image::iterator iter;
for (iter=begin(); iter != end(); ++iter)
{
element &elem(*iter);
if (Key == k)
{
return(elem);
}
}
throw("Not found");
}
};

I think the reason this isn't working is due to the const declaration
of the method.


It is due to you trying to use a non-const-iterator on a const
container. Use const_iterator instead of iterator.


I Can't use const_iterator because tof the overhead involved

element elem = *iter

make an entire copy of the object for every object in the list
(i.e. at every iteration of the for loop)
This is very inefficient...

Jul 22 '05 #5

"JustSomeGuy" <No***@ucalgary.ca> wrote in message
news:40***************@ucalgary.ca...
Rolf Magnus wrote:
JustSomeGuy wrote:
this doesn't want to compile....
Always post the full error message.
class image : public std::list<element>
{
element getElement(key k) const
{
image::iterator iter;
for (iter=begin(); iter != end(); ++iter)
{
element &elem(*iter);
if (Key == k)
{
return(elem);
}
}
throw("Not found");
}
};

I think the reason this isn't working is due to the const declaration
of the method.


It is due to you trying to use a non-const-iterator on a const
container. Use const_iterator instead of iterator.


I Can't use const_iterator because tof the overhead involved

element elem = *iter


cont_iterator does NOT force you to do a value copy. Just return (*iter).
Why add the element& anyway? If you continue to insist on an local scoped
reference, it needs to be a const reference.

const element& elem(*iter);

or
element const& elem(*iter);

Your getElement member function is specified 'const', so that's why you need
to use const_iterator.

make an entire copy of the object for every object in the list
(i.e. at every iteration of the for loop)
This is very inefficient...


In the above code, probably not if 'Key == k' considering 'k' never changes
in this scope, and I assume Key is a glo or a data member, and is not
modified in this code.

Jeff F
Jul 22 '05 #6
Jeff Flinn wrote:
"JustSomeGuy" <No***@ucalgary.ca> wrote in message
news:40***************@ucalgary.ca...
Rolf Magnus wrote:
JustSomeGuy wrote:

> this doesn't want to compile....

Always post the full error message.

> class image : public std::list<element>
> {
> element getElement(key k) const
> {
> image::iterator iter;
> for (iter=begin(); iter != end(); ++iter)
> {
> element &elem(*iter);
> if (Key == k)
> {
> return(elem);
> }
> }
> throw("Not found");
> }
> };
>
> I think the reason this isn't working is due to the const declaration
> of the method.

It is due to you trying to use a non-const-iterator on a const
container. Use const_iterator instead of iterator.
I Can't use const_iterator because tof the overhead involved

element elem = *iter


cont_iterator does NOT force you to do a value copy. Just return (*iter).
Why add the element& anyway? If you continue to insist on an local scoped
reference, it needs to be a const reference.

const element& elem(*iter);

or
element const& elem(*iter);

Your getElement member function is specified 'const', so that's why you need
to use const_iterator.
make an entire copy of the object for every object in the list
(i.e. at every iteration of the for loop)
This is very inefficient...


In the above code, probably not if 'Key == k' considering 'k' never changes
in this scope, and I assume Key is a glo or a data member, and is not
modified in this code.


Sorry that was supposed to be:
if (elem.Key == k)


Jeff F


Jul 22 '05 #7

"JustSomeGuy" <No***@ucalgary.ca> wrote in message
news:40***************@ucalgary.ca...
Rolf Magnus wrote:
JustSomeGuy wrote:
this doesn't want to compile....


Always post the full error message.
class image : public std::list<element>
{
element getElement(key k) const
{
image::iterator iter;
for (iter=begin(); iter != end(); ++iter)
{
element &elem(*iter);
if (Key == k)
{
return(elem);
}
}
throw("Not found");
}
};

I think the reason this isn't working is due to the const declaration
of the method.


It is due to you trying to use a non-const-iterator on a const
container. Use const_iterator instead of iterator.


I Can't use const_iterator because tof the overhead involved

element elem = *iter

make an entire copy of the object for every object in the list
(i.e. at every iteration of the for loop)
This is very inefficient...


So just change

element &elem(*iter);

to

const element &elem(*iter);

and use a const iterator.

If const made any difference at all to the efficiency of a C++ program it
wouldn't be part of the language.

john
Jul 22 '05 #8
On Fri, 18 Jun 2004 20:11:33 GMT, red floyd <no*****@here.dude> wrote:
Phlip wrote:
Don't inherit std::list<>.

Generally, only inherit to override a virtual method. STL does not use any
virtuals.


Earlier I asked a question about inheriting std::priority_queue<>. It
seems that priority_queue is designed to be inherited (as it has
protected members), even though it has no virtuals.

There are many reasons to inherit, even if something has no virtuals,
such as adding new behavior, even though it doesn't modify existing
(Note that I was using private inheritance).

Blanket bans may not be a good thing.


Why inherit from a class which you cannot use polymorphically in the
first place?

Since the base class destructor is not virtual, it is not called when
your derived class is destroyed. I suppose one could call it
explicitly from the derived class' destructor, but this is hardly good
design. Likewise, since the member functions in std::list are not
virtual, you must not override them in the derived class because that
would hide the base class functions.

It is quite possible to implement what you want to do using
delegation, or containment -- your class has a data member of type
std::list, and you can write forwarding functions for any of the
std::list methods which you would like to use in your own class. I did
this once in order to extend std::string, which also has no virtual
destructor. It is a bit tedious to write all the one-liner functions
to forward to std::list, but at least you end up with something that
works properly.

Really, you shouldn't inherit from this one. Some STL classes are
designed for inheritance, such as std::exception (which DOES have a
virtual destructor).
--
Bob Hairgrove
No**********@Home.com
Jul 22 '05 #9
Bob Hairgrove wrote:
Earlier I asked a question about inheriting std::priority_queue<>. It
seems that priority_queue is designed to be inherited (as it has
protected members), even though it has no virtuals.

There are many reasons to inherit, even if something has no virtuals,
such as adding new behavior, even though it doesn't modify existing
(Note that I was using private inheritance).

Blanket bans may not be a good thing.
Why inherit from a class which you cannot use polymorphically in the
first place?


Because you might want to inherit functionality from some class but
don't want to use it polymorphically.
Since the base class destructor is not virtual, it is not called when
your derived class is destroyed.
That's wrong. Things only go wrong if a derived object is dynamically
allocated _and_ destroyed through a pointer to the base class. In this
case, the derived part isn't properly destroyed. Any other way of
creating/destroying the object will just work fine.
I suppose one could call it
explicitly from the derived class' destructor, but this is hardly good
design. Likewise, since the member functions in std::list are not
virtual, you must not override them in the derived class because that
would hide the base class functions.
Hiding and overriding are two different concepts. Anyway, if you do
that, then hiding the base class's function is exactly what you want.
It is quite possible to implement what you want to do using
delegation, or containment -- your class has a data member of type
std::list, and you can write forwarding functions for any of the
std::list methods which you would like to use in your own class.


And if you want to use most functions of std::list, you will have the
boring task to write a whole lot of forwarding functions. What is the
advantage over just inheriting them and not needing to write any code
for them?
Note that when using containment and forwarding functions, you still
cannot use it as a polymorphic replacement for std::list, so by
deriving from std::list, you didn't lose _any_ functionality. The only
thing that's different is that you have less work when deriving.

Jul 22 '05 #10
On Sat, 19 Jun 2004 11:29:24 +0200, Rolf Magnus <ra******@t-online.de>
wrote:
Bob Hairgrove wrote:
Earlier I asked a question about inheriting std::priority_queue<>. It
seems that priority_queue is designed to be inherited (as it has
protected members), even though it has no virtuals.

There are many reasons to inherit, even if something has no virtuals,
such as adding new behavior, even though it doesn't modify existing
(Note that I was using private inheritance).

Blanket bans may not be a good thing.


Why inherit from a class which you cannot use polymorphically in the
first place?


Because you might want to inherit functionality from some class but
don't want to use it polymorphically.


I overlooked the fact that he was using private inheritance.
Since the base class destructor is not virtual, it is not called when
your derived class is destroyed.


That's wrong. Things only go wrong if a derived object is dynamically
allocated _and_ destroyed through a pointer to the base class. In this
case, the derived part isn't properly destroyed. Any other way of
creating/destroying the object will just work fine.


Of course, with private inheritance this isn't a problem anymore.
I suppose one could call it
explicitly from the derived class' destructor, but this is hardly good
design. Likewise, since the member functions in std::list are not
virtual, you must not override them in the derived class because that
would hide the base class functions.


Hiding and overriding are two different concepts. Anyway, if you do
that, then hiding the base class's function is exactly what you want.
It is quite possible to implement what you want to do using
delegation, or containment -- your class has a data member of type
std::list, and you can write forwarding functions for any of the
std::list methods which you would like to use in your own class.


And if you want to use most functions of std::list, you will have the
boring task to write a whole lot of forwarding functions. What is the
advantage over just inheriting them and not needing to write any code
for them?
Note that when using containment and forwarding functions, you still
cannot use it as a polymorphic replacement for std::list, so by
deriving from std::list, you didn't lose _any_ functionality. The only
thing that's different is that you have less work when deriving.


--
Bob Hairgrove
No**********@Home.com
Jul 22 '05 #11
Bob Hairgrove wrote:

Since the base class destructor is not virtual, it is not called when
your derived class is destroyed.


The base class destructor is always called when an object of a derived
type is destroyed.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #12
Rolf Magnus wrote:

In this
case, the derived part isn't properly destroyed.


Not exactly true (if one wants to be pendantic).

Destroying a derived class though a pointer to a base class with no virtual
destructor results in *undefined behaviour*, which means anything can
happen.

Max
Jul 22 '05 #13
On Sat, 19 Jun 2004 08:48:05 -0400, Pete Becker <pe********@acm.org>
wrote:
Bob Hairgrove wrote:

Since the base class destructor is not virtual, it is not called when
your derived class is destroyed.


The base class destructor is always called when an object of a derived
type is destroyed.


Yes. I seem to have gotten this backwards.

Sorry for the FUD.
--
Bob Hairgrove
No**********@Home.com
Jul 22 '05 #14
Bob Hairgrove wrote:
Why inherit from a class which you cannot use polymorphically in the
first place?


Because you might want to inherit functionality from some class but
don't want to use it polymorphically.


I overlooked the fact that he was using private inheritance.


Me too ;-)

Jul 22 '05 #15
Rolf Magnus wrote:
Bob Hairgrove wrote:

Why inherit from a class which you cannot use polymorphically in the
first place?

Because you might want to inherit functionality from some class but
don't want to use it polymorphically.


I overlooked the fact that he was using private inheritance.

Me too ;-)


I'd also point out that std::priority_queue<> has *protected* members,
which implies that it was designed to be inherited from.

I essentially had:

class MyData { ... };
class MyQueue : private std::priority_queue<MyData>
{
public:
MyQueue() : std::priority_queue<MyData>() { }
~MyQueue() { }
using std::priority_queue<MyData>::push;
// other using declarations to bring the entire interface forward
void my_additional_functionality(); // that uses protected
// members of priority_queue<>
};
Jul 22 '05 #16

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

7 posts views Thread by ree | last post: by
4 posts views Thread by Grey Plastic | last post: by
3 posts views Thread by Dave C | last post: by
15 posts views Thread by Dave | last post: by
4 posts views Thread by James Aguilar | last post: by
16 posts views Thread by Peter Ammon | last post: by
17 posts views Thread by Adrian Hawryluk | last post: by
reply views Thread by Long March | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.