Difficultly Handling Vectors

Oct 20, 2014 at 8:23am
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?
Oct 20, 2014 at 8:37am
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 Oct 20, 2014 at 8:40am
Oct 20, 2014 at 8:46am
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;
};
Oct 20, 2014 at 8:59am
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 Oct 20, 2014 at 8:59am
Oct 20, 2014 at 9:00am
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.
Oct 20, 2014 at 9:10am
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*

Oct 20, 2014 at 10:47am
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.