Difficultly Handling Vectors

I am working my way through the book Head First Design Patterns. The books code is based in Java; however, the explanations of the design patterns are exceptional. Currently, I am working on the observer design pattern and I am having difficulty working with a vector.

My compilation issues consist of a warning and a error:

-Warning 1 warning C4018: '<' : signed/unsigned mismatch c:\testprojects\design patterns observer\design patterns observer\weatherdata.cpp 30 1 Design Patterns Observer
-Error 2 error C2819: type 'std::vector<IObserver *,std::allocator<_Ty>>' does not have an overloaded member 'operator ->' c:\testprojects\design patterns observer\design patterns observer\weatherdata.cpp 32 1 Design Patterns Observer
-Error 3 error C2039: 'update' : is not a member of 'std::vector<IObserver *,std::allocator<_Ty>>' c:\testprojects\design patterns observer\design patterns observer\weatherdata.cpp 32 1 Design Patterns Observer


My definition of vector type as public member variable inside the class header file:
std::vector<class IObserver *> *observers = new std::vector < class IObserver * >; Is this the correct way? I understand this is not java. Code sill throws errors without the "new"

Code snippet recieving a Visual Studio highlighted error: (Expression must have a pointer type)
1
2
3
4
5
6
7
void WeatherData::notifyObserver(IObserver *o)
{
	for (int i = 0; i < observers->size(); i++)
	{
		observers[i]->update(temperature, humidity, pressure);
	}
}


Can anyone help me get past this hurdle?
Morning,
Do you really need a pointer to a vector of pointers?
If not just declare something like:

std::vector<IObserver> observers;
in your class.

The warning is just telling you that size() method returns an unsigned int ( size_type ) and you've declared i to be an int (not too worrying.)

regarding the errors.. There doesn't appear to be an update() method defined in your IObserver class. is this correct?

Also, you're passing in a IObserver pointer but are not doing anything with it. Are you aware of this? How big is your IObserver class? Can you post it's declaration?

edit: forgot to say... I also think that java design patterns book is excellent at explaining things, but there will be enough OO differences between java and c++ to make the examples not 1 to 1 transferable.
Last edited on
This is the WeatherData Class:

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
#pragma once
#include "ISubject.h"
#include "IObserver.h"
#include <vector>

class WeatherData : public ISubject
{
public:
	WeatherData();
	~WeatherData();

	//Interface Functions
	virtual void registerObserver(IObserver *o);
	virtual void removeObserver(IObserver *o);
	virtual void notifyObserver();
	
	//Concrete Functions
	void measurementsChanged();
	void setMeasurements(float temperature, float humidity, float pressure);

private:
	std::vector<class IObserver *> *observers;
	float temperature;
	float humidity;
	float pressure;
};


This is the .cpp file
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
#include "WeatherData.h"

WeatherData::WeatherData()
{
	temperature = 0.0;
	humidity = 0.0;
	pressure = 0.0;
}


WeatherData::~WeatherData()
{
	delete observers;
}

void WeatherData::registerObserver(IObserver *o)
{
	observers->push_back(o);
}

void WeatherData::removeObserver(IObserver *o)
{
	observers->pop_back(); //Need to figure out away to find the specific index of the Observer
}

void WeatherData::notifyObserver()
{
       //ERROR
	for (int i = 0; i < observers->size(); i++)
	{
		observers[i]->update(temperature, humidity, pressure);
	}
}

void WeatherData::measurementsChanged()
{

}

void WeatherData::setMeasurements(float temperature, float humidity, float pressure)
{

}


This is the IObserver Class

1
2
3
4
5
6
7
8
9
10
11
12
#pragma once
#include <string>
class IObserver
{
public:
	IObserver();
	virtual ~IObserver();

	//Observer Interface Functions
	virtual void update(float tmp, float humidity, float pressure) {};
	static int ID;
};
Form what you've shown, "observers" is a pointer to a vector, not an array of vectors. I imagine, you've push_back()ed some number of "IObserver *" to the vector it references, i.e. you've done "observers->push_back(...);" and so on. To access the elements you would have to do "(*observers)[i]->update(...)" That's why you get the "Expression must have a pointer type" message, you're treating a pointer as if it were an object.

Also the proper place for that definition is in the constructor initialisation list (or body)
Last edited on
I'll ask again, do you really need a pointer to a vector of pointers?

I just changed your vector definition to
std::vector<IObserver*> observers;

and changed the -> to . for all method calls and apart from the minor warning it now compiles.
Thanks Tipaye and Mutexe for helping solve the problem.

Mutexe,

I was using pointers to force myself to "learn them". I would of never guessed (*observers)[i] as the solution. I have followed your advise and edited the code to contain a "vector" of IObserver*

Nice one. If you are writing fresh code i would use smart pointers, e.g.:
http://en.cppreference.com/w/cpp/memory/unique_ptr

However, it is a great idea to learn how the old-style 'raw' pointers work. In my opinion.
Topic archived. No new replies allowed.