How to make function work with arrays of different pointers?
-
SAn schrieb:
I am using "_" to distinguish between types (classes) names and objects names.
http://www.cse.iitb.ac.in/~karkare/Gc/coding/
Names starting with _ (underscore) and __ (two underscores) are reserved for compiler writers. These should be avoided.
-
OK. I will try to avoid names starting with "_"
And I did not write the last message containing "idiot". This is a someone's joke.
-
just pass to the function by pointer/ref to base.
class A { }; class B : public A { }; class C { }; void func(A const& val) { //do something } int main(int, char**) { A a; B b; C c; func(a); //works func(b); //should work as well func(c); //compile time error }
-
inp, yes. The problem is to do the same behaviour with arrays of pointers, not just with pointers.
-
how about using functors and foreach/transform ?
-
SAn schrieb:
inp, yes. The problem is to do the same behaviour with arrays of pointers, not just with pointers.
yes, i got that.
but A** isnt B**.
anyway A** can store elements of type B*
so why not use a constistent scheme and use just basettype pointerarraysclass A { public: virtual void WhoAmI() { printf("A\n"); } }; class B: public A { public: virtual void WhoAmI() { printf("B\n"); } }; void func(A** arr, size_t num) { for (size_t i = 0; i < num; ++i) arr[i]->WhoAmI(); } int main(argc, char**) { A** a = new A*[1]; A** b = new A*[1]; a[0] = new A(); b[0] = new B(); func(a, 1); func(b, 1); return 0; }
-
sorry for my sloppy coding though

-
SAn schrieb:
inp, yes. The problem is to do the same behaviour with arrays of pointers, not just with pointers.
That is not possible (well, unless you write your own array/vector-class to simulate it - and then there's more than one way to do it too). The reason is simply that when you convert a pointer to a derived class to a pointer to an (accessible and unambigous) base class that converted pointer ceases to point to your derived class. What you can do is converting rvalue pointers, i.e. the values of pointer objects. What you cannot do is to convert lvalues of pointer type to other lvalues of pointer type which pointed to different objects. And that is really what you do when you have an array
struct Foo {}; struct Bar : Foo {}; Bar* x[N];and try to cast it
(Foo*(&)[N])x;Because that means that you want to treat each element of x as if it was an object containing a pointer to Foo. For one, pointers to different types may not have the same object representation. But more importantly, they may not even have the same value when converting one to another (using a suitable point of reference: void*). One pointer points to the Bar object and the other to the Foo subobject within the Bar object and those two need not share the same address. As a general rule - laid down in ancient C times - two different (living - so we ignore unions here) objects do not have the same address. There are only two exceptions to that: the first member of class may have the same address as the class itself (and in case of PODs that is required) and a base class subobject may (but need not) have the same address as the object of the derived class.
This comes down to a simple rule: never treat arrays polymorphically. Polymorphism applies to individual pointers and references only, never to collections of them.
-
I can not use virtual functions due to performance issues.
But the previous messages bring me to the following idea:
inline void CheckType(A *a){;} template <typename T> void ShowArrayA(vector<T*> &Array) { if(!Array.size()) return; CheckType(Array[0]); //Check if T derived from A. I think the clever compiler will generate empty code for this for(vector<T*>::size_type n(0); n<Array.size(); ++n) cout << Array[n]->memberA << ' '; cout << endl; }This looks ugly, but I think it should work.
camper, thank you for the detailed explanation.
But more importantly, they may not even have the same value when converting one to another
This is new to me. I thought that each pointer points to the very first byte of the object. And base class subobject always have the same address as the object of the derived class.
But now I understand that it is compiler-specific.
-
SAn schrieb:
I can not use virtual functions due to performance issues.
there are plenty ways how to counter performance problems.
-
SAn schrieb:
But more importantly, they may not even have the same value when converting one to another
This is new to me. I thought that each pointer points to the very first byte of the object. And base class subobject always have the same address as the object of the derived class.
But now I understand that it is compiler-specific.
Think multiple inheritance.
-
How about iterators? Seems simpler and more flexible to me.
template <typename InputIterator> void ShowArrayA( InputIterator first, InputIterator last ) { for ( ; first != last; ++first) std::cout << (*first)->memberA << ' '; std::cout << endl; }#include <algorithm> #include <iterator> #include <boost/iterator/indirect_iterator.hpp> std::ostream& operator<<( std::ostream& out, _A const& obj ) { return out << obj.memberA; } template <typename InputIterator> void ShowArrayA( InputIterator first, InputIterator last ) { std::copy( boost::make_indirect_iterator(first), boost::make_indirect_iterator(last), std::ostream_iterator<_A>(std::cout, " ")); std::cout << std::endl; }// test ShowArrayA(ArrayAOldStyle, ArrayAOldStyle + numObjects); ShowArrayA(ArrayANewStyle.begin(), ArrayANewStyle.end()); ShowArrayA(ArrayBOldStyle, ArrayBOldStyle + numObjects); ShowArrayA(ArrayBNewStyle.begin(), ArrayBNewStyle.end());