Scope - Public v Protected

I am more after education here rather than solving the issue, because this flies against my understanding of public and protected (and private), or I am missing a nuanced problem here. Either way I would appreciate an expert’s opinion.

The project is irrelevant, but effectively I am using a class to deal with an element of drawing to a CView via a public function. When I start the application it creates a new instance of the class (I use a pointer to reference it). The class constructor populates the graphical data, and then the draw function is successfully called. Ostensibly the draw function runs through an array of points to generate the required lines on the CView – this works fine. The array is protected.

I also call the public draw function following a window resize, the function is called correctly but the points aren’t draw. The problem seems that even though the public draw function uses protected members of the same class, some of them seem to be out of scope (the postNum is not correctly reference, it appears out of scope). The array (also protected) is fine, I believe this is because arrays are always referenced as pointers behind the scene. But I am perplexed why the class function cannot access its own protected members. If I make the offending items public, it works just fine.

I am either missing something fundamental with public and protected (and by inference private) or I am missing a scope issue with my class pointer (but that wouldn’t help me explain why some of the other members remain valid).

I hope the following code snippets show enough for you to telling me where I am being stupid…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class CTerrain : public CObject
{
public:
	CTerrain(HWND hWnd);
	~CTerrain() {};
	void Draw(CDC* pDC);
	COLORREF colourErase,colourDraw;

protected:
	RECT clientRect;
	POINT	terrain [2000];				// terrain data
	int postNum;						// number of posts
	float postSpacing;					// pixels between the posts
	
private:
	float getRand (int min, int max);
	void blendTerrain (int x1, int x2);
	
};


1
2
3
4
5
6
7
8
9
10
11
void CTerrain::Draw(CDC* pDC)
{
	pDC->FillSolidRect(&clientRect,colourErase);

	pDC->MoveTo(terrain[0].x,terrain[0].y);
	
	for (int i=1; i<=postNum; i++)
	{
		pDC->LineTo(terrain[i].x,terrain[i].y);
	}
}

CView Class .cpp

This bit always works

1
2
3
4
5
void CTrajectoryView::startProcess()
{
	Terrain=&(CTerrain (GetSafeHwnd()));
	Terrain->Draw(GetWindowDC());
}



This bit will only work if I make postNum public vice protected in Terrain.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void CTrajectoryView::OnDraw(CDC* pDC)
{
	CTrajectoryDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	if (StartUp)
		startProcess();
	else
	{
		Terrain->Draw(pDC);
	}
}


The problem is not due to protected/public issues. It looks like a scope/pointer issue.

Your problem is here:

1
2
3
4
5
void CTrajectoryView::startProcess()
{
	Terrain=&(CTerrain (GetSafeHwnd()));
	Terrain->Draw(GetWindowDC());
}


CTerrain(GetSafeHwnd()) creates an unnamed temporary object. I'll call this object "foo".

Terrain is then set to point to "foo".

However, because "foo" is temporary, it goes out of scope immediately (either just before the Draw() call, or after the startProcess function ends -- I forget exactly when temporary objects die).

So as soon as foo goes out of scope and dies... "Terrain" becomes a bad pointer, since the object it points to no longer exists. At that point, anything you try to do with it (like draw) will have undefined behavior (hence the weirdness you're seeing).

You need to give the object a more permanent scope. A temporary object will not do. There are several ways you can accomplish this:

1) Change Terrain to be an object instead of a pointer.

2) Allocate the object with new (Terrain = new CTerrain(GetSafeHwnd());). This will require you to delete Terrain; when done to prevent memory leaks.

3) Use technique #2, but wrap it in a smart pointer so you don't have to worry about cleanup. std::shared_ptr will work nicely.
Disch

I figured it out the other day, I feel very stupid.... basics! But thank you for taking the time to reply.
Topic archived. No new replies allowed.