Hi,
A colleague has some code like this:
class CMyObject {
// Bunch of Member functions
}
class CMyObjectList: public std::vector<CMyObject>
{
// Bunch of member functions
}
I need to inherit the functionality of his object and list as well as add
some of my own:
class CMyPersonalObject: public CMyObject
{
// More stuff
}
class CMyPersonalObjectList: public CMyObjectList
{
// More stuff
}
But if I pass in CMyPersonalObjectList to a function, and then try to assign
the CMyPersonalObject to a local variable of that type, I get a compiler
error telling me that I cannot convert CMyObject to CMyPersonalObject... the
compiler thinks the list I passed in is made of the parent objects.
What is going on and how do I fix it?
Thanks,
B 26 10647
BCC wrote: But if I pass in CMyPersonalObjectList to a function, and then try to assign the CMyPersonalObject to a local variable of that type, I get a compiler error telling me that I cannot convert CMyObject to CMyPersonalObject... the compiler thinks the list I passed in is made of the parent objects.
What is going on and how do I fix it?
Would need to see the code where the assignment is made.
However, as std::vector doesn't have a virtual destructor it
shouldn't really be being used as a base class. That isn't
your actual problem though.
On Thu, 23 Oct 2003 23:47:14 GMT, "BCC" <br***@akanta.com> wrote: A colleague has some code like this:
class CMyObject { // Bunch of Member functions }
Missing semicolon.
class CMyObjectList: public std::vector<CMyObject> { // Bunch of member functions }
Ditto.
Without further information this inheritance is a little suspicious.
I can thing of good reasons to inherit from std::string, but not std::vector.
I need to inherit the functionality of his object and list as well as add some of my own:
class CMyPersonalObject: public CMyObject { // More stuff }
class CMyPersonalObjectList: public CMyObjectList { // More stuff }
But if I pass in CMyPersonalObjectList to a function, and then try to assign the CMyPersonalObject to a local variable of that type,
There is no relationship between CMyPersonalObjectList and CMyPersonalObject
in what you have shown, so the above seems meaningless.
I get a compiler error telling me that I cannot convert CMyObject to CMyPersonalObject...
The compiler is right, you cannot do that unless you provide a conversion.
the compiler thinks the list I passed in is made of the parent objects.
Where on earth did you get that absurd idea? Compilers don't think.
What is going on
See e.g. <url: http://news.google.com/>.
and how do I fix it?
Perhaps follow the advice of Michael Moore?
On Thu, 23 Oct 2003 23:47:14 GMT, BCC <br***@akanta.com> wrote: Hi,
A colleague has some code like this:
class CMyObject { // Bunch of Member functions }
class CMyObjectList: public std::vector<CMyObject> { // Bunch of member functions }
I need to inherit the functionality of his object and list as well as add some of my own:
class CMyPersonalObject: public CMyObject { // More stuff }
class CMyPersonalObjectList: public CMyObjectList { // More stuff }
But if I pass in CMyPersonalObjectList to a function, and then try to assign the CMyPersonalObject to a local variable of that type, I get a compiler error telling me that I cannot convert CMyObject to CMyPersonalObject... the compiler thinks the list I passed in is made of the parent objects.
What is going on and how do I fix it?
Thanks, B
std::vector is a template . CMyObjectList should also be a template, at
least if you want to have personalobject list.
template <class T> CObjectList : public std::vector<T> {
some more
};
typedef CObjectList<CMyPersonalObject> CMyPersonalObjectList;
--
grzegorz
"Alf P. Steinbach" <al***@start.no> wrote in message
news:3f****************@News.CIS.DFN.DE... the compiler thinks the list I passed in is made of the parent objects.
Where on earth did you get that absurd idea? Compilers don't think.
Understatement of the year. :-)
-Mike
"BCC" <br***@akanta.com> wrote in message
news:6M********************@newssvr21.news.prodigy .com... Hi,
A colleague has some code like this:
class CMyObject { // Bunch of Member functions }
class CMyObjectList: public std::vector<CMyObject> { // Bunch of member functions }
I need to inherit the functionality of his object and list as well as add some of my own:
class CMyPersonalObject: public CMyObject { // More stuff }
class CMyPersonalObjectList: public CMyObjectList { // More stuff }
But if I pass in CMyPersonalObjectList to a function, and then try to
assign the CMyPersonalObject to a local variable of that type, I get a compiler error telling me that I cannot convert CMyObject to CMyPersonalObject...
the compiler thinks the list I passed in is made of the parent objects.
It won't work, because the vector contains CMyObjects, not
CMyPersonalObjects. So whenever you insert a CMyPersonalObject in that
vector, it'll get "truncated" to it's base type. You might be able to use a
vector of pointers to (dynamically-allocated) CMyObjects (+derivatives)
instead, but you'll run into other problems:
- Manual memory allocation is difficult and error-prone (but "smart pointer"
libraries might help, see for example www.boost.org )
- You'll have to downcast the stored addresses all the time
- I think it is wrong to have CMyPersonalObjectList as a subclass of
CMyObjectList, because such hierarchy permits insertions of CMyObjects into
CMyPersonalObjectList (you might want to do a search on "Liskov Substitution
Principle" to learn why this is a bad idea. For example read this article: http://www.brent.worden.org/articles...rinciple.html).
What exactly are you trying to do? Maybe there's a better way to do it. What is going on and how do I fix it?
Thanks, B
Mike Wahler wrote: "Alf P. Steinbach" <al***@start.no> wrote in message news:3f****************@News.CIS.DFN.DE...
the compiler thinks the list I passed in is made of the parent objects.
Where on earth did you get that absurd idea? Compilers don't think.
Understatement of the year. :-)
OP must have confused "The Compiler That Thinks" with "The Thinking
Man's Compiler."
/david :-)
--
"As a scientist, Throckmorton knew that if he were ever to break wind in
the echo chamber, he would never hear the end of it."
lilburne wrote: However, as std::vector doesn't have a virtual destructor it shouldn't really be being used as a base class.
There is no problem with using it as a base class as long as you don't
destroy the object through a pointer to std::vector.
Rolf Magnus wrote: lilburne wrote:
However, as std::vector doesn't have a virtual destructor it shouldn't really be being used as a base class.
There is no problem with using it as a base class as long as you don't destroy the object through a pointer to std::vector.
And you ensure that how?
lilburne wrote: Rolf Magnus wrote:
lilburne wrote:
However, as std::vector doesn't have a virtual destructor it shouldn't really be being used as a base class.
There is no problem with using it as a base class as long as you don't destroy the object through a pointer to std::vector.
And you ensure that how?
You don't do it.
--
Pete Becker
Dinkumware, Ltd. ( http://www.dinkumware.com)
Pete Becker wrote: lilburne wrote:
Rolf Magnus wrote:
lilburne wrote: However, as std::vector doesn't have a virtual destructor it shouldn't really be being used as a base class.
There is no problem with using it as a base class as long as you don't destroy the object through a pointer to std::vector.
And you ensure that how?
You don't do it.
I take it you mean: you don't inherit from a class that
doesn't contain a virtual destructor, not that you don't
delete a pointer to a class that doesn't have a virtual
destructor.
lilburne wrote: Pete Becker wrote:
lilburne wrote:
Rolf Magnus wrote:
lilburne wrote: >However, as std::vector doesn't have a virtual destructor it >shouldn't really be being used as a base class.
There is no problem with using it as a base class as long as you don't destroy the object through a pointer to std::vector.
And you ensure that how?
You don't do it.
I take it you mean: you don't inherit from a class that doesn't contain a virtual destructor, not that you don't delete a pointer to a class that doesn't have a virtual destructor.
You take it wrong. Pay attention to context.
--
Pete Becker
Dinkumware, Ltd. ( http://www.dinkumware.com)
Pete Becker wrote: lilburne wrote:
Pete Becker wrote:
lilburne wrote:
Rolf Magnus wrote: >lilburne wrote: > > > > >>However, as std::vector doesn't have a virtual destructor it >>shouldn't really be being used as a base class. > > >There is no problem with using it as a base class as long as you don't >destroy the object through a pointer to std::vector. >
And you ensure that how?
You don't do it.
I take it you mean: you don't inherit from a class that doesn't contain a virtual destructor, not that you don't delete a pointer to a class that doesn't have a virtual destructor.
You take it wrong. Pay attention to context.
Amazing:
#include <iostream>
#include <memory>
using namespace std;
class A {
public:
A();
~A();
};
class B : public A {
string s;
public:
B();
~B();
};
A::A() { cout << "A::A" << endl;}
A::~A() { cout << "A::~A" << endl;}
B::B() { cout << "B::B" << endl;}
B::~B() { cout << "B::~B" << endl;}
int main()
{
auto_ptr<A> a(new B);
return 0;
}
lilburne wrote: You take it wrong. Pay attention to context.
Amazing:
You wrote bad code, having been told it's bad. What's your point?
--
Pete Becker
Dinkumware, Ltd. ( http://www.dinkumware.com)
Pete Becker wrote: lilburne wrote:
You take it wrong. Pay attention to context.
Amazing:
You wrote bad code, having been told it's bad. What's your point?
What was bad about it?
lilburne wrote: Pete Becker wrote:
lilburne wrote:
You take it wrong. Pay attention to context.
Amazing:
You wrote bad code, having been told it's bad. What's your point?
What was bad about it?
PLONK.
--
Pete Becker
Dinkumware, Ltd. ( http://www.dinkumware.com)
Pete Becker wrote: lilburne wrote:
Pete Becker wrote:
lilburne wrote:
>You take it wrong. Pay attention to context. >
Amazing: You wrote bad code, having been told it's bad. What's your point?
What was bad about it?
PLONK.
Tsk! You jump in to sanction using a class inheritance
design, that not only restricts how the heirarchy may be
used, but which also has the potential to cause resource
leakage, and then become all sniffy.
Its no good simply saying 'don't do it', because it will be
done. If you took 10 'C++' programmers at random and asked
"What does the following program print?" you'd be lucky to
get the correct answer from 4 of them. Ask the 4 that got it
right the same question again having removed virtual from
A's destructor and you might get 2 left.
class A {
public:
virtual void func1() { cout << "a::func1" << endl; }
void func2() { cout << "a::func2" << endl; }
virtual void func3() { cout << "a::func3" << endl; }
virtual ~A() { cout << "a::~a" << endl; }
};
class B {
public:
virtual void func1() { cout << "b::func1" << endl; }
void func2() { cout << "b::func2" << endl; }
void func3() { cout << "b::func3" << endl; }
virtual ~B() { cout << "b::~b" << endl; }
};
int main()
{
B* b = new B;
A* a = b;
a->func1();
a->func2();
a->func3();
b->func1();
b->func2();
b->func3();
delete a;
return 0;
}
Its astonishing how many programmers do not understand the
import of the keyword virtual. But you know that.
On Fri, 24 Oct 2003 21:58:53 +0100, lilburne <li******@godzilla.net> wrote: Pete Becker wrote:
lilburne wrote:
You take it wrong. Pay attention to context.
Amazing:
You wrote bad code, having been told it's bad. What's your point?
What was bad about it?
You're destroying a non-polymorphic class object polymorphically (through a
pointer to the base class object).
But you knew that.
It's illogical to ban usage of a feature just because that feature _can_
be abused, since almost all language features _can_ be abused, and I think
your use of such an illogical argument was the reason why Pete plonked you.
Alf P. Steinbach wrote: On Fri, 24 Oct 2003 21:58:53 +0100, lilburne <li******@godzilla.net> wrote:
Pete Becker wrote:
lilburne wrote:
>You take it wrong. Pay attention to context. >
Amazing: You wrote bad code, having been told it's bad. What's your point?
What was bad about it?
You're destroying a non-polymorphic class object polymorphically (through a pointer to the base class object).
But you knew that.
It's illogical to ban usage of a feature just because that feature _can_ be abused, since almost all language features _can_ be abused, and I think your use of such an illogical argument was the reason why Pete plonked you.
It is unlikely that Pete Becker would derive a class from
a base that has a non-virtual destructure, without some
overriding reason to do so. Because he knows it is a
resource leak waiting to happen, and that safer alternatives
are usually available.
To pretend that you can ensure that the polymorphic deletion
on such a class heirarchy can be avoid just by saying "Don't
do it" is ridiculous. The OP not only has an inheritance
tree of depth four, but is also inheriting from a class that
already exists. As there are already functions in the system
that process the base class polymorphism is going to occur.
Certain language features ought to be used with caution, IMO
one should learn how to use them properly before you start
to abuse them.
On Sat, 25 Oct 2003 02:55:25 +0100, lilburne <li******@godzilla.net> wrote: Certain language features ought to be used with caution, IMO one should learn how to use them properly before you start to abuse them.
Well, modest that I am I find it unlikely that either Pete or I don't
know how to use inheritance properly, and I find it unlikely that either
of us would abuse the mechanism.
Perhaps you're referring to the OP?
But the OP didn't code inheritance from std::vector; he's, er, inherited
that code...
Perhaps, then, you're referring to your own abusive example code?
lilburne wrote: You wrote bad code, having been told it's bad. What's your point?
What was bad about it?
You're destroying a non-polymorphic class object polymorphically (through a pointer to the base class object).
But you knew that.
It's illogical to ban usage of a feature just because that feature _can_ be abused, since almost all language features _can_ be abused, and I think your use of such an illogical argument was the reason why Pete plonked you.
It is unlikely that Pete Becker would derive a class from a base that has a non-virtual destructure, without some overriding reason to do so. Because he knows it is a resource leak waiting to happen,
No, it's not. Polymorphically destroying an object of that class is.
A knife can be a useful tool, and it isn't evil. Hoever, using it to
stab people is. Almost everything can be destructive if you want it to
be.
and that safer alternatives are usually available.
To pretend that you can ensure that the polymorphic deletion on such a class heirarchy can be avoid just by saying "Don't do it" is ridiculous.
You could also reinterpret_cast the pointer to char* and delete that
one. It will also result in improper deletion. But why would anyone do
such a stupid thing?
Certain language features ought to be used with caution, IMO one should learn how to use them properly before you start to abuse them.
Nope. One should learn how to use them and never abuse them at all.
Alf P. Steinbach wrote: On Sat, 25 Oct 2003 02:55:25 +0100, lilburne <li******@godzilla.net> wrote:
Certain language features ought to be used with caution, IMO one should learn how to use them properly before you start to abuse them.
Well, modest that I am I find it unlikely that either Pete or I don't know how to use inheritance properly, and I find it unlikely that either of us would abuse the mechanism.
Then why sanction it for others?
Perhaps you're referring to the OP?
But the OP didn't code inheritance from std::vector; he's, er, inherited that code...
The OP was proposing deriving 3 additional class from it. If
he can't repair the initial inheritance scheme he can at
least not inherit it, or perhaps reduce the potential risk
by giving the initial inheriting class a virtual destructor.
Perhaps, then, you're referring to your own abusive example code?
The code presented isn't abusive. It simply demonstrated the
problem you are likely to have when you have an inheritance
tree whose base consists of a non virtual destructor. It
could even exist in legacy code, which the deriver is
unaware of, and whose original coder certainly wasn't
abusing the language.
Rolf Magnus wrote: lilburne wrote:
>You wrote bad code, having been told it's bad. What's your point? >
What was bad about it?
You're destroying a non-polymorphic class object polymorphically (through a pointer to the base class object).
But you knew that.
It's illogical to ban usage of a feature just because that feature _can_ be abused, since almost all language features _can_ be abused, and I think your use of such an illogical argument was the reason why Pete plonked you.
It is unlikely that Pete Becker would derive a class from a base that has a non-virtual destructure, without some overriding reason to do so. Because he knows it is a resource leak waiting to happen,
No, it's not. Polymorphically destroying an object of that class is. A knife can be a useful tool, and it isn't evil. Hoever, using it to stab people is. Almost everything can be destructive if you want it to be.
As day follows night someone will delete an object of the
class polymorphically, there may already be doing so. There
might be code in the system that deletes pointers of the
base class. They may not, nor should they, even know that
the base pointer they are dealing with is of a derived class.
In any case by inheriting from the base you are implicitly
restricting the problem space that your class can be validly
used in, and you have passed a charged on to maintainence
due to a lazy implementation. All future users of the class
have to remember not to destroy via the base, or to call any
method that might do. But you could have avoid the cost by
using composition rather than inheritance.
lilburne wrote:
[...] In any case by inheriting from the base you are implicitly restricting the problem space that your class can be validly used in, and you have passed a charged on to maintainence due to a lazy implementation. All future users of the class have to remember not to destroy via the base, or to call any method that might do. But you could have avoid the cost by using composition rather than inheritance.
No thankyou. http://google.com/groups?selm=3DF9C6...EE37E%40web.de
(Subject: Re: blocking inheritance)
regards,
alexander.
Pete Becker <pe********@acm.org> writes >>However, as std::vector doesn't have a virtual destructor it >>shouldn't really be being used as a base class. > > > There is no problem with using it as a base class as long as you don't > destroy the object through a pointer to std::vector. >
And you ensure that how?
You don't do it.
I would have thought that would be quite difficult.
If you work as part of a team of developers, or for a large company
where one team expects to reuse code from another team, you'd have to
carefully document the class. Even if your fellow developers remember to
trace the chain of inheritance right back to the base class and check,
how many of them will know that std::vector doesn't have a virtual
destructor? (I didn't know until I read this thread.)
If you're a one man band, you still might post some of your code on the
internet, sell it to somebody, or be very busy and need to subcontract a
project.
Even if you know (somehow) that you will never do the above, you might
need to do a rush job and think: "OK, I can inherit from my XYZ class,
job done and dusted." Then you find yourself in the debugger at three in
the morning, drinking jolt cola or black coffee.
All the same, there are times when I would like to be able to inherit
from a std::vector or other container. I tend to typedef my STL
container declarations:
typedef std::vector<int> CsectorList;
But then I find that I can't forward declare them, because you can't
forward declare a typedef. If I could safely do:
class CsectorList:public std::vector<int>{};
Then I could forward declare this as:
class CsectorList;
Anyone got any ideas for safely achieving this?
--
Simon Elliott http://www.ctsn.co.uk/
Simon Elliott wrote: Pete Becker <pe********@acm.org> writes
>However, as std::vector doesn't have a virtual destructor it >shouldn't really be being used as a base class.
There is no problem with using it as a base class as long as you don't destroy the object through a pointer to std::vector.
And you ensure that how? You don't do it.
I would have thought that would be quite difficult.
You know, I know it, ... All the same, there are times when I would like to be able to inherit from a std::vector or other container. I tend to typedef my STL container declarations:
typedef std::vector<int> CsectorList;
But then I find that I can't forward declare them, because you can't forward declare a typedef. If I could safely do:
class CsectorList:public std::vector<int>{};
Then I could forward declare this as:
class CsectorList;
Anyone got any ideas for safely achieving this?
The question I'd ask is why you want to typedef the thing,
other than to avoid adding #include <vector>. I suppose it
might make it easier to turn it into a std::list, or
whatever, at some later stage. The problem is that you
haven't really hidden the fact that its a vector and haven't
stopped clients from using vector specific operations. I've
been there.
Another motivation I've seen is when someone inherits a
container and adds application specific operations to the
new class. The problem with this is that clients can still
treat it as a bare std::container circumventing any
application specific invariants you might want to impose.
IOW you don't protect access to the container.
Personally I'd either seperate the container specific
element from the application specific operations, or use the
has-a relationship between the classes. I prefer the later.
The result is I believe more robust over time.
lilburne <li******@godzilla.net> writes The question I'd ask is why you want to typedef the thing, other than to avoid adding #include <vector>. I suppose it might make it easier to turn it into a std::list, or whatever, at some later stage.
There's the clarity issue as well. This is discussed quite well here: http://www.gotw.ca/gotw/046.htm
But I'm fairly sure that you still have to #include <vector>. More
unpleasantly, if your container is a
std::vector<large_nontrivial_class>
you also need to #include "large_nontrivial_class.h"
So classes which didn't need to know about either std::vector or
large_nontrivial_class still need both includes.
If we were to inherit from std::container<large_nontrivial_class>, the
inherited class could be forward declared and neither of these includes
would be necessary.
The problem is that you haven't really hidden the fact that its a vector and haven't stopped clients from using vector specific operations. I've been there.
Another motivation I've seen is when someone inherits a container and adds application specific operations to the new class. The problem with this is that clients can still treat it as a bare std::container circumventing any application specific invariants you might want to impose. IOW you don't protect access to the container.
You could always inherit from it privately, but see below.
Personally I'd either seperate the container specific element from the application specific operations, or use the has-a relationship between the classes. I prefer the later. The result is I believe more robust over time.
Yes, and this would also be safer if the container had not got a virtual
destructor. On the other hand, there may be some usefulness in exposing
the underlying container, as this allows users to apply all the generic
algorithms from the standard library to your class.
--
Simon Elliott http://www.ctsn.co.uk/ This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Jason Heyes |
last post by:
To my understanding, std::vector does not use reference counting to avoid
the overhead of copying and initialisation. Where can I get a reference
counted implementation of std::vector? Thanks.
|
by: Janina Kramer |
last post by:
hi ng,
i'm working on a multiplayer game for a variable number of players and on the client side, i'm using a std::vector<CPlayer> to store
informatik about the players. CPlayer is a class that...
|
by: Anonymous |
last post by:
Is there a non-brute force method of doing this?
transform() looked likely but had no predefined function object.
std::vector<double> src;
std::vector<int> dest;
...
|
by: Michael Hopkins |
last post by:
Hi all
I want to create a std::vector that goes from 1 to n instead of 0 to n-1.
The only change this will have is in loops and when the vector returns
positions of elements etc. I am calling...
|
by: Ross A. Finlayson |
last post by:
I'm trying to write some C code, but I want to use C++'s std::vector.
Indeed, if the code is compiled as C++, I want the container to
actually be std::vector, in this case of a collection of value...
|
by: zl2k |
last post by:
hi, c++ user
Suppose I constructed a large array and put it in the std::vector in a
function and now I want to return it back to where the function is called.
I can do like this:
...
|
by: Peter Olcott |
last post by:
I am trying to refer to the same std::vector in a class by two different names,
I tried a union, and I tried a reference, I can't seem to get the syntax right.
Can anyone please help? Thanks
|
by: aaragon |
last post by:
I am trying to create a vector of type T and everything goes fine until
I try to iterate over it. For some reason, the compiler gives me an
error when I declare
std::vector<T>::iterator iter;...
|
by: jubelbrus |
last post by:
Hi
I'm trying to do the following.
#include <vector>
#include <boost/thread/mutex.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/tuple/tuple.hpp>
class {
|
by: lllomh |
last post by:
Define the method first
this.state = {
buttonBackgroundColor: 'green',
isBlinking: false, // A new status is added to identify whether the button is blinking or not
}
autoStart=()=>{
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 4 Oct 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM)
The start time is equivalent to 19:00 (7PM) in Central...
|
by: Aliciasmith |
last post by:
In an age dominated by smartphones, having a mobile app for your business is no longer an option; it's a necessity. Whether you're a startup or an established enterprise, finding the right mobile app...
|
by: NeoPa |
last post by:
Hello everyone.
I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report).
I know it can be done by selecting :...
|
by: NeoPa |
last post by:
Introduction
For this article I'll be using a very simple database which has Form (clsForm) & Report (clsReport) classes that simply handle making the calling Form invisible until the Form, or all...
|
by: Teri B |
last post by:
Hi, I have created a sub-form Roles. In my course form the user selects the roles assigned to the course.
0ne-to-many. One course many roles.
Then I created a report based on the Course form and...
|
by: nia12 |
last post by:
Hi there,
I am very new to Access so apologies if any of this is obvious/not clear.
I am creating a data collection tool for health care employees to complete. It consists of a number of...
|
by: isladogs |
last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM).
In this month's session, Mike...
|
by: GKJR |
last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...
| |