I made 2 classes, Point and Point3D:

Point.h:

#ifndef POINT_H
#define POINT_H

#include <iostream>

template <typename T>
class Point
{
protected:
	T X,Y,Z;
public:
	
	Point(const T x, const T y, const T z) : X(x), Y(y), Z(z) {}

	T getX() {return X;};
	T getY() {return Y;};
	T getZ() {return Z;};

	void Output();

};

template< typename T>
void Point<T>::Output()
{ 
	std::cout << "x: " << X << " y: " << Y << " z: " << Z << std::endl;
}

#endif

Point3D.h:

#ifndef POINT3D_H
#define POINT3D_H

#include "Point.h"

template <typename T>
class Point3D : public Point<T>
{
	T X,Y,Z;
	public:
		Point3D(const T x, const T y, const T z) : Point<T>(x,y,z) {}

		void Output3D();
};

template< typename T>
void Point3D<T>::Output3D()
{
	std::cout << "3D" << std::endl;
	
	//these both show junk values
	//std::cout << "X: " << this->X << std::endl;
	//std::cout << "X: " << X << std::endl;
	
	//this says "there are no arguments to 'getX' that depend on a template parameter, so a declaration of 'getX' must be available
	double x = getX();
	std::cout << "X: " << x << std::endl;
}

#endif

Test.cpp

#include <iostream>

#include "Point3D.h"

int main(int argc, char* argv[])
{
	
	Point3D<double> C(1.2,2.3,4.5);
	C.Output(); //works fine
	C.Output3D(); //doesn't work

	return 0;
}

The problem is with the Output3D function. It doesn't seem to be able to access the protected variables in Point (they just are garbage values). If I try to use the accessors, there are compiler errors (described with comments in the above code).

Can anyone see what I am doing wrong here?

Thanks,

David

Hi

The Output() member uses X,Y,Z from class Point<T> but Output3D() is a member of Point3D<T> and uses the X,Y,Z members from Point3D<T> which are never assigned. The Point3D<T> constructor passes the parameters to the base class Point<T> and never assigns X,Y,Z in Point3D<T>. Should work if you remove X,Y and Z from Point3D<T>, these members are protected in Point<T> and should be accessable from Point3D<T>.

I thought what the Point3D constructor was doing is calling the Point constructor which then set X,Y,Z. Since Point3D inherits from Point, Point3D should also have access to those variables since they are protected, no?

The junk values are because you declare in both Point and Point3D:

T X,Y,Z;

but, you only initialize those belonging to Point in the construction.

As far as it running as posted, I had no problems running it and the data appeared correctly as coded to me, but maybe it's because you commented out the problems?

Ah, I see - I declared X,Y,Z in Point3D as well - doh! That actually is an interesting question - so there are now 2 different X,Y,Z that can both be used? this->X from Point3D would clearly access the Point3D version, but then how would you access the Point version of X?

Actually - now that I remove X,Y,Z from Point3D I am getting the error that I was attempting to mimic with this example: "error: 'X' was not declared in this scope.

from Point3D.h...

template< typename T>
void Point3D<T>::Output3D()
{
	std::cout << "X: " << X << std::endl; //the error is on this line

}

Shouldn't X be available from Point since Point3D inherits from Point?

Thanks for the help so far!

Dave

I uncommented those two lines after commenting out the unnecessary var declarations, and I run just fine. Did you change something else?

I don't think so? Here is the current version:

Point3D.h

#ifndef POINT3D_H
#define POINT3D_H

#include "Point.h"

template <typename T>
class Point3D : public Point<T>
{
	
	public:
		Point3D(const T x, const T y, const T z) : Point<T>(x,y,z) {}

		void Output3D();
};

template< typename T>
void Point3D<T>::Output3D()
{
[B]	std::cout << "X: " << X << std::endl; //compiler error on this line[/B]
}

#endif

Point.h

#ifndef POINT_H
#define POINT_H

#include <iostream>

template <typename T>
class Point
{
protected:
	T X,Y,Z;
public:
	
	Point(const T x, const T y, const T z) : X(x), Y(y), Z(z) {}

	T getX() {return X;};
	T getY() {return Y;};
	T getZ() {return Z;};

	void Output();

};

template< typename T>
void Point<T>::Output()
{ 
	std::cout << "x: " << X << " y: " << Y << " z: " << Z << std::endl;
}

#endif

Test:

#include <iostream>
#include <vector>


#include "Point3D.h"

int main(int argc, char* argv[])
{
	
	Point3D<double> C(1.2,2.3,4.5);
	C.Output();
	C.Output3D();

	return 0;
}

I don't see any difference except I crammed it all in one header file. I am using VS2008 compiler. Here is the header code I have:

#ifndef POINT3D_H
#define POINT3D_H
 
#ifndef POINT_H
#define POINT_H
 
#include <iostream>
 
template <typename T>
class Point
{
protected:
	T X,Y,Z;
public:
 
	Point(const T x, const T y, const T z) : X(x), Y(y), Z(z) {}
 
	T getX() {return X;};
	T getY() {return Y;};
	T getZ() {return Z;};
 
	void Output();
 
};
 
template< typename T>
void Point<T>::Output()
{ 
	std::cout << "x: " << X << " y: " << Y << " z: " << Z << std::endl;
}
 
#endif
//////////////////////

//////////////////////
template <typename T>
class Point3D : public Point<T>
{
	//T X,Y,Z;
	public:
		Point3D(const T x, const T y, const T z) : Point<T>(x,y,z) {}
 
		void Output3D();
};
 
template< typename T>
void Point3D<T>::Output3D()
{
	std::cout << "3D" << std::endl;
 
	//these both show junk values
	std::cout << "X: " << this->X << std::endl;
	std::cout << "X: " << X << std::endl;
 
	//this says "there are no arguments to 'getX' that depend on a template parameter, so a declaration of 'getX' must be available
	double x = getX();
	std::cout << "X: " << x << std::endl;
}
 
#endif
commented: thanks for the response! +5

Interesting... I threw that code into a single header file (copy and pasted what you just posted) and I get the same "error: 'X' was not declared in this scope". I am using g++ from gcc version 4.4.0. Can anyone else confirm this behavior (either working or not)?

Thanks,

David

daviddoria,

Error message says - "there are no arguments to 'getX' that depend on a template parameter, so a declaration of 'getX' must be available. "

In Output3D, getX() is not used in a dependent context, so the compiler will look for a name declared at the enclosing namespace scope or the global scope. It will not look into the base class, since that is dependent and you may declare specializations of Base even after declaring Derived, so the compiler can't really know what getX() would refer to.

In order to make it clear that you want the member of the base class, you need to defer lookup until instantiation time, at which the base class is known.

For this, you need to access getX() in a dependent context, by either using

this->getX();

, or using

Point<T>::getX();
commented: great answer! +5

Interesting - thanks! Finally a case where you MUST use the 'this' pointer haha.

All is well now, thanks again all!

David

Well, one more question actually. If in Point I define:

public:
	typedef double MyDouble;

Then in Point3D I try to do:

template< typename T>
void Point3D<T>::Output3D()
{
	std::cout << "X: " << this->X << std::endl;

[B]//none of these work![/B]
MyDouble a; //doesn't work
	//typename this->MyDouble a; //doesn't work
	//this->MyDouble a; //doesn't work
	//typename MyDouble a; //doesn't work
}

What is the syntax I have to use to access that typedef in the derived class?

Thanks,

David

I found that

typename Point<T>::MyDouble a;

works. Why would this->MyDouble not work?

Dave

Because it is a defined class type and not an instance type.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.