Vectors and Derived Classes

I'm writing some code to do various geometric calculations on geographical data. Below is the relevant portion and the compiler output. Any ideas about what's going wrong and how to fix it would be greatly appreciated. Thanks.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include<vector>
using std::vector;

struct GeoBounds;

struct GeoBoundable {
	virtual GeoBounds getBounds() const;
};

struct GeoPoint: public GeoBoundable {
	double longitude;
	double latitude;

	GeoPoint() {}
	GeoPoint(double lon, double lat) : longitude(lon), latitude(lat) {}

	GeoBounds getBounds() const;
};

struct GeoPolygon: public GeoBoundable {
	vector<GeoPoint> points;

	GeoBounds getBounds() const;
};

struct GeoBounds {
	GeoPoint minimum;
	GeoPoint maximum;
 
	GeoBounds(const double minLong, const double maxLong, const double minLat, const double maxLat) {
		minimum = GeoPoint(minLong, minLat);
		maximum = GeoPoint(maxLong, maxLat);
	}
	GeoBounds(const vector<GeoBoundable> &list) { // Gives the smallest bounds containing all the GeoBoundable objects in the list
		minimum = GeoPoint( 1E30,  1E30);
		maximum = GeoPoint(-1E30, -1E30);
		for(unsigned int i = 0; i < list.size(); i++) {
			GeoBounds elementBounds = list[i].getBounds();
			if(elementBounds.minimum.longitude < minimum.longitude)               minimum.longitude = elementBounds.minimum.longitude;
			if(maximum.longitude               < elementBounds.maximum.longitude) maximum.longitude = elementBounds.maximum.longitude;
			if(elementBounds.minimum.latitude  < minimum.latitude)                minimum.latitude  = elementBounds.minimum.latitude;
			if(maximum.latitude                < elementBounds.maximum.latitude)  maximum.latitude  = elementBounds.maximum.latitude;
		}
	}
};

GeoBounds GeoPoint::getBounds() const {
	return GeoBounds(longitude, longitude, latitude, latitude);
}

GeoBounds GeoPolygon::getBounds() const {
	return GeoBounds(points);
}


1>Compiling...
1>GeoGeometry.cpp
1>c:\users\peterson.ben\documents\visual studio 2008\projects\test\test\geogeometry.cpp(52) : error C2440: '<function-style-cast>' : cannot convert from 'const std::vector<_Ty>' to 'GeoBounds'
1>        with
1>        [
1>            _Ty=GeoPoint
1>        ]
1>        No constructor could take the source type, or constructor overload resolution was ambiguous
Last edited on
That error is because the class GeoPolygon contains a vector of GeoPoint

1
2
3
4
5
struct GeoPolygon: public GeoBoundable {
	vector<GeoPoint> points; //**here

	GeoBounds getBounds() const;
}


So this call
1
2
3
GeoBounds GeoPolygon::getBounds() const {
	return GeoBounds(points); // **this call here
}


will fail because the GeoBounds constructor expects a vector reference of GeoBoundable -
GeoBounds(const vector<GeoBoundable> &list) { // Gives the smallest bounds containing all the GeoBoundable objects in the list

A vector<GeoPoint> class is not directly convertible to a vector<GeoBoundable> class - hence
the error.


Maybe you meant to have the GeoBounds constructor take a vector reference of GeoPoint - like this:
GeoBounds(const vector<GeoPoint> &list) { // Gives the smallest bounds containing all the GeoBoundable objects in the list


**I also see another error waiting in the wings but we will cross that bridge when we come to it**
You are trying to upcast a concrete class. You can't do this. You can only upcast references and pointers.

Basically, it can't convert a std::vector<GeoPoint> into a std::vector<GeoBoundable>

In my opinion, the constructor would be much better implemented like this:

Line 34:
 
template<typename Iterator_>GeoBounds(Iterator_ begin, Iterator_ end) {


Line 37-38:
1
2
for(;begin!=end;++begin) {
GeoBounds elementBounds = begin->getBounds();


Line 52:
 
return GeoBounds(points.begin(), points.end());


You can also scrap the GeoBoundable Base, it is not necessary with static polymorphism.
Last edited on
OK, I understand. I made another constructor just for vector<GeoPoint>:

GeoBounds(const vector<GeoPoint>& points);

I'd still like to keep the constructor for vector<GeoBoundable*>. Here's another GeoBoundable class I use:

1
2
3
4
5
6
7
8
9
struct MetroNode: public GeoBoundable {
	int      index;
	string   type;
	GeoPoint location;

	MetroNode() {}
	MetroNode(int i, string t, GeoPoint loc) : index(i), type(t), location(loc) {}
	GeoBounds getBounds() const;
};


I wanted to compute the bounds of a vector<MetroNode*>, so I first tried this:

1
2
3
vector<MetroNode*> nodes;
...
GeoBounds graphBounds(nodes);


But that didn't work because I guess MetroNode* doesn't automatically convert to GeoBoundable*. I found that this works instead:

GeoBounds graphBounds(vector<GeoBoundable*>(nodes.begin(), nodes.end()));

Is this the easiest way to get the bounds of "nodes"?
See my edited post above, I think this would be much better with static polymorphism.
I posted my last comment before reading kev82's. It looks like I was on the right track, but I like your method better. Thanks!
Topic archived. No new replies allowed.