473,387 Members | 1,545 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Vector and derived classes objects

Consider a class - lets call it CObjectHolderClass that has a
collection of object pointers like

std::vector<CBaseClass*> base_class_vec;

as member var. Now somewhere in my CObjectHolderClass I do

CDerived1* p_derived1 = new CDerived1();
base_class_vec.push_back(derived1);

In CObjectHolderClass, i just use the public interface of CBaseClass.

If I derive another class - lets say CDerived2 from CBaseClass, I have
to change my CObjectHolderClass to do something like

CDerived2* p_derived2 = new CMyOtherBaseClass();
base_class_vec.push_back(p_derived2);

Trouble is, I have to modify CObjectHolderClass for different derived
classes. How do I get around this?

My guess is this borders on some type of 'design pattern' (an area I
haven't delved into yet) or perhaps a template solution but I'm
confused on how.

Untested or working source examples would be greatly appreaciated.
This alleaviates the need for me my potentially silly follow up
questions.

As always, thanks in advance.
Jul 22 '05 #1
11 1709
ma740988 wrote:
Consider a class - lets call it CObjectHolderClass that has a
collection of object pointers like

std::vector<CBaseClass*> base_class_vec;

as member var. Now somewhere in my CObjectHolderClass I do

CDerived1* p_derived1 = new CDerived1();
base_class_vec.push_back(derived1);

In CObjectHolderClass, i just use the public interface of CBaseClass.

If I derive another class - lets say CDerived2 from CBaseClass, I have
to change my CObjectHolderClass to do something like

CDerived2* p_derived2 = new CMyOtherBaseClass();
base_class_vec.push_back(p_derived2);

Trouble is, I have to modify CObjectHolderClass for different derived
classes. How do I get around this?
A template, perhaps...
My guess is this borders on some type of 'design pattern' (an area I
haven't delved into yet) or perhaps a template solution but I'm
confused on how.

Untested or working source examples would be greatly appreaciated.
This alleaviates the need for me my potentially silly follow up
questions.


#include <vector>

class Base {};

class ObjectHolder {
std::vector<Base*> base_class_vec;
public:
template<class D> void addDerived(D* d) {
base_class_vec.push_back(d);
}
};

class Derived1 : public Base {};
class Derived2 : public Base {};

int main() {
ObjectHolder blah;
blah.addDerived(new Derived1());
blah.addDerived(new Derived2());
}

(this example doesn't clean after itself, but you can add it, can't you?)

HTH

V
Jul 22 '05 #2
* Victor Bazarov:
ma740988 wrote:
Consider a class - lets call it CObjectHolderClass that has a
collection of object pointers like

std::vector<CBaseClass*> base_class_vec;

as member var. Now somewhere in my CObjectHolderClass I do

CDerived1* p_derived1 = new CDerived1();
base_class_vec.push_back(derived1);

In CObjectHolderClass, i just use the public interface of CBaseClass.

If I derive another class - lets say CDerived2 from CBaseClass, I have
to change my CObjectHolderClass to do something like

CDerived2* p_derived2 = new CMyOtherBaseClass();
base_class_vec.push_back(p_derived2);

Trouble is, I have to modify CObjectHolderClass for different derived
classes. How do I get around this?


A template, perhaps...


The OP states that only the public interface of CBaseClass is used.

Hence, declaring the internal pointers as CBaseClass*, and passing in
an object factory serving such pointer, will do (here ignoring the probably
incorrect reference to CMyOtherBaseclass).

The main problem is that the examples the OP gives are not exception
safe; should be e.g.
std::auto_ptr<CBaseClass> p_derived = my_derived_factory->newObject();

base_class_vec.push_back( p_derived.get() ); // May throw.
p_derived.release();

--
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?
Jul 22 '05 #3
Victor Bazarov <v.********@comAcast.net> wrote in message news:<QQ***************@newsread1.dllstx09.us.to.v erio.net>...
ma740988 wrote: [...]
int main() {
ObjectHolder blah;
blah.addDerived(new Derived1());
blah.addDerived(new Derived2());
}

(this example doesn't clean after itself, but you can add it, can't you?)

That I could do. :) Thanks for the help
Jul 22 '05 #4
al***@start.no (Alf P. Steinbach) wrote in message news:<41****************@news.individual.net>...
[...]
A template, perhaps...


The OP states that only the public interface of CBaseClass is used.

Hence, declaring the internal pointers as CBaseClass*, and passing in
an object factory serving such pointer, will do (here ignoring the probably
incorrect reference to CMyOtherBaseclass).

The main problem is that the examples the OP gives are not exception
safe; should be e.g.
std::auto_ptr<CBaseClass> p_derived = my_derived_factory->newObject();

base_class_vec.push_back( p_derived.get() ); // May throw.
p_derived.release();


I thought of a auto_ptr solution though I might add I'm not sure if
I'm following you here but I'll investigate with a 'quick' example.
Jul 22 '05 #5
al***@start.no (Alf P. Steinbach) wrote in message news:<41****************@news.individual.net>...
[...]


std::auto_ptr<CBaseClass> p_derived = my_derived_factory->newObject();

base_class_vec.push_back( p_derived.get() ); // May throw.
p_derived.release();


I'm unaware of how push_back will 'throw'. ie' I'm not aware/dont
know which exception is thrown if push_back fails or is it a no-op???
Could you elaborate.
Jul 22 '05 #6
"ma740988" <ma******@pegasus.cc.ucf.edu> wrote...
al***@start.no (Alf P. Steinbach) wrote in message
news:<41****************@news.individual.net>...
[...]


std::auto_ptr<CBaseClass> p_derived =
my_derived_factory->newObject();

base_class_vec.push_back( p_derived.get() ); // May throw.
p_derived.release();


I'm unaware of how push_back will 'throw'. ie' I'm not aware/dont
know which exception is thrown if push_back fails or is it a no-op???
Could you elaborate.


push_back may cause reallocation, which can fail, in that case
'std::bad_alloc'
is thrown. RTFM.

V
Jul 22 '05 #7
al***@start.no (Alf P. Steinbach) wrote in message news:<41****************@news.individual.net>...
[...]
base_class_vec.push_back( p_derived.get() ); // May throw.
p_derived.release();


I asked earlier about how push_back will throw. I realize now that
I've been mis-reading Josuttis and parts of the manual. I'm using
google newsreader so I'm unsure if your or anyone else responded
nonetheless, I understand now.
It boils down to this:

push_back may need to increase the size of the vector. If it does, it
will use its allocator, and the allocator could throw an exception if
it can't allocate the memory. The function will also use the
contained class's assignment operator, or possibly its copy
constructor, and that function could throw an exception. So the
push_back function will not throw an exception itself, (now comes the
part I was missing earlier) but it might call something else that
does.
Jul 22 '05 #8
"Victor Bazarov" <v.********@comAcast.net> wrote in message news:<77tjd.57469$HA.40359@attbi_s01>...
[...]
push_back may cause reallocation, which can fail, in that case
'std::bad_alloc'
is thrown. RTFM.

I did and that was the problem.

Alf P. Steinbach wrote
[quote]
The main problem is that the examples the OP gives are not exception
safe; should be e.g.
[/qoute]

Now given:

std::vector<CBaseClass*> base_class_vec;
// later
CDerived1* p_derived1 = new CDerived1();
base_class_vec.push_back(derived1);

Since I am using just vector of pointers, the copy-ctor or assign-op
wont be called for the objects the pointer points to, hence I dont see
any way an exception can be thrown there with my push_back.

Bottom line as I understand it:
If you dont provide your own allocator class, the push_back of
std::vector is a no-op on failure. It wont throw any exception if it
fails, Josuttis as also mentiones that in his STL book.
Jul 22 '05 #9
ma740988 wrote:
[...]
Since I am using just vector of pointers, the copy-ctor or assign-op
wont be called for the objects the pointer points to, hence I dont see
any way an exception can be thrown there with my push_back.
Huh? push_back beyond the capacity of the vector _requires_ that the
storage for that vector is grown. That means reallocation. That also
means the original storage has to stay around until all the copying
has competed. If your vector occupies at least half the memory that
your process is allowed to have, there is no way in hell push_back can
succeed without throwing to tell you that you've run out of memory.
Bottom line as I understand it:
If you dont provide your own allocator class, the push_back of
std::vector is a no-op on failure. It wont throw any exception if it
fails, Josuttis as also mentiones that in his STL book.


I think you got this wrong. _If_ the push_back throws (to indicate the
failure), _then_ it's a NOP. IOW, the container doesn't change, all
iterators are valid, no reallocation happens. Reread that place in
Josuttis' book. I am 101% certain that all he writes there is the repeat
of 23.1/10. Just think a little: how can the push_back fail and _not_
throw an exception?

V
Jul 22 '05 #10
Victor Bazarov <v.********@comAcast.net> wrote in message news:<ai****************@newsread1.dllstx09.us.to. verio.net>...
ma740988 wrote:
[...]
Since I am using just vector of pointers, the copy-ctor or assign-op
wont be called for the objects the pointer points to, hence I dont see
any way an exception can be thrown there with my push_back.


Huh? push_back beyond the capacity of the vector _requires_ that the
storage for that vector is grown. That means reallocation. That also
means the original storage has to stay around until all the copying
has competed. If your vector occupies at least half the memory that
your process is allowed to have, there is no way in hell push_back can
succeed without throwing to tell you that you've run out of memory.


[...]

Victor, appreaciate your patience but this reminds me of a course in
pertubation techniques where it took me 3 texts and days later before
I saw the light hence bear with me once more. I'm not arguing a throw
of bad_alloc, I understand. So now consider:

class X
{
std::string kdx;
public:
X() { }
};

int main()
{
X *ptr_x = new X();
std::size_t Jdx = sizeof (ptr_x);
std::cout << Jdx << std::endl;

std:vector<X*> my_vec;
my_vec.push_back(ptr_x);
std::cout << my_vec.size() << std::endl;
std::cout << my_vec.capacity() << std::endl;

delete ptr_x;
}

The output
4
1
1

on my platform. Now my_vec is a single byte. That said, I envision
it would require for me then to store a 'slew' of pointers (beyond the
capacity of the vectory - whatever number that is) to my_vec for me to
run out of memory. Correct?
Jul 22 '05 #11
ma740988 wrote:


class X
{
std::string kdx;
public:
X() { }
};

int main()
{
X *ptr_x = new X();
std::size_t Jdx = sizeof (ptr_x);
std::cout << Jdx << std::endl;

std:vector<X*> my_vec;
my_vec.push_back(ptr_x);
std::cout << my_vec.size() << std::endl;
std::cout << my_vec.capacity() << std::endl;

delete ptr_x;
}

The output
4
1
1

on my platform. Now my_vec is a single byte.
How did you deduce that?
my_vec is certainly not a single byte.
That said, I envision
it would require for me then to store a 'slew' of pointers (beyond the
capacity of the vectory - whatever number that is) to my_vec for me to
run out of memory. Correct?


Right. But capacity has nothing to do with it. capacity is just the number
of array entries the vector has allocated right now. size() returns the
number of entries which are actually in use. If you continue to push_back
things to the vector, its size will grow until finally it reaches capacity()
(That is: all allocted entries have been used). When this happens, the vector
tries to increase capacity by allocating a larger junk of memory and continue.
It is clear that this cannot happen forever. Eventually the vector wil have
used up all available memory and ....

Look. Don't make things so complicated. A far amount of programming concepts
are taken directly from real live. Say you want to write some things down on paper.
What do you do? You take a notebook and start writing. Say you have written
(pushed back) 2 pages. So the capacity of the notebook is (lets say) 40 pages
(the total number of pages, some of them are unused) and the size of it (the
part that is used) is 2 pages. If you continue to write in your notebook, the size
increases to the capacity (the book gets full).
When this happens, what do you do? You increase the capacity by buying a notebook
with more pages. Since you don't want more then 1 notebook around, you first
copy the content from the old notebook to the new notebook. Then you continue
writing until the size has reached up to that capacity, etc., etc.
Eventually you will be in need for a notebook with so many pages, that you have
used up all the paper on the planet earth. When this happens, your notebook dealer
will tell you that you brought him into troubles getting such a large notebook, he
will throw an exception.

See the similarities?

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: Frank Bormann | last post by:
Hi guys, I'm a C++ beginner. I was wondering if there is a generalized vector base class, through which I could pass a pointer to any kind of vector to a function, regardless of what type of...
5
by: canned.net | last post by:
I have a class Scene that has several subclasses: World, Vault, etc. I fill a vector with these classes and then cannot go through and delete them. What's the trick to deleting pointers from a...
8
by: Manuel | last post by:
Hi! If I've a vector filled with abstract classes, can I push in it the derived classes too? Even if derived classes have new methods? I've done some experiments, and it seem I can push the...
9
by: kathy | last post by:
I am using std::vector in my program: func() { std::vector <CMyClass *> vpMyClass; vpMyClass.push_back(new CMyClass()); vpMyClass.push_back(new CMyClass()); vpMyClass.push_back(new...
24
by: toton | last post by:
Hi, I want to have a vector like class with some additional functionality (cosmetic one). So can I inherit a vector class to add the addition function like, CorresVector : public...
7
by: Thomas | last post by:
I am compiling with g++ the fol. class: template<typename E> class C_vector_ : public std::vector<E> { private:
3
by: nw | last post by:
Hi, I have three classes, a template pure virtual base class, a template derived class and a third which I would like to use to store copies of the derived class. The code looks like this: ...
6
by: Jia | last post by:
Hi all, I have a class foo which has a static vector of pointers of type base class, and a static function to set this vector. #include <iostream> #include <vector> using namespace std;...
3
by: Rob | last post by:
I have these classes (elided methods): class Base { public: Base(string name) {...} }; class Derived : public Base {
9
by: Julian | last post by:
Hi, I have a vector defined like this: std::vector<Load*LoadList; which is populated with different objects of classes that are derived from 'Load'. I need to make a copy of this list during...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
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...
0
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
0
BarryA
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...
1
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...
0
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...
0
Oralloy
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,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.