template <class T>
class baseclass{
protected:
T data;
public:
baseclass(){};
void setData(T d);
};
template<class T>
void baseclass<T>::setT(T d){
data = d;
}
Shown above is my base class, one protected member variable, one setter.
template <class T>
class aclass : public baseclass<T>
{
public:
aclass(T d);
};
template<class T>
aclass<T>::aclass(T d){
setData(d); <---WORKS
data = d; <---DOESN'T WORK
}
Now this is my subclass of the first. For some reason, accessing the protected member variable directly is not working though I believe it ought to. However, accessing the setter works fine. I'm a noob with C++, I'm sure I'm missing something obvious.
The reason that this doesn't work is a quirk in the way that C++ templates do name resolution. In particular, if you have a template class that inherits from another class that depends on a template type (as you're doing in this case), you cannot access the members of that base class directly without giving the compiler a hint about where to look. This is the cause of the error you're getting.
To fix this, you can rewrite your constructor as
template<class T>
aclass<T>::aclass(T d){
setData(d);
this->data = d;
}
Now that the compiler knows that data must somehow be a member of aclass<T>, it can find what it's looking for.
Interestingly, you should also be getting an error on the previous line for the same reason. I'm not sure why it decided to compile. To fix this, you can either do this:
template<class T>
aclass<T>::aclass(T d){
this->setData(d);
this->data = d;
}
Alternatively, you can add a using declaration to tell the compiler that aclass inherits the setData method from its parent class. In the class declaration, consider adding this line:
template <class T>
class aclass : public baseclass<T>
{
public:
aclass(T d);
using baseclass<T>::setData;
};
Like the this-> for data members, this trick makes it unambiguous where the name setData comes from and helps the compiler know what you're talking about.
Hope this helps!
Related
I have a question as I cannot explain why something works where I probably have made a mistake. Maybe somebody kind can help me to improve my C++ culture by explaining to me why this is so.
For better transparency I simplifiy the code quite a bit.
I have a template virtual class that is like this:
template<class Node>
class tXmlNode
{
public:
tXmlNode();
virtual ~tXmlNode();
protected:
Node* node;
}
;
From this I derive several classes.
Mostly I derive from it another template class such as this one:
template<class Part>
class tXmlMove : public tXmlNode<Part>
{
public:
tXmlMove(Part* part);
~tXmlMove();
protected:
int n_translate;
};
with this implementation (reduced to the constructor):
template<class Part>
inline tXmlMove<Part>::tXmlMove(Part* part) : tXmlNode<Part>(part)
{
//do some construction
}
;
As you can see I delegate some part of the construction to the parent class constructor. Works fine.
Now I have another derived class but which is derived from a specialized parent class (the specialisation is a self-specialisation but from other classes with similar specialized parent it works exactly as for this one):
class tXmlCaseDefinition : public tXmlNode<tXmlCaseDefinition>
{
public:
tXmlCaseDefinition();
tXmlCaseDefinition(const pugi::xml_node& parent);
~tXmlCaseDefinition();
protected:
int n_shapes;
}
;
(I guess it is due to the specialization that I do not need to construct this class as a template class.)
Its not-default constructor is implemented as follows:
nXml::tXmlPart::tXmlPart(
const pugi::xml_node& parent,
const int npos) : tXmlNode(parent, npos), this_id(""), this_type(""), description("")
{
}
;
As you can see I did not delegate to the parent constructor by using tXmlNode<tXmlCaseDefinition>(parent,npos) but simply tXmlNode(parent,npos). I didn't pay attention to that and it works for some mysterious reason. I simply cannot understand why. Can somebody explain?
Also do I need to use tXmlNode<Part>(part) or can I use tXmlNode(part) instead for classes not derived from the specialized parent class or is this only possible when I have a spezialized parent?
Thank you very much!
Within the definition of a template class (more formally, the "current instantiation"), there is something called an injected-class-name, which is simply the name of the template sans arguments. For example:
template<class T>
struct Foo
{
Foo* ptr; // refers to Foo<T>
};
When you derive from a templated class, the base class' injected-class-name is inherited. Therefore you can also refer to the base class sans template arguments (assuming the name is accessible; some ancestor didn't privately inherit from it):
template<class T>
struct Base
{
};
struct Derived : Base<int>
{
Base* ptr; // refers to Base<int>
};
cppreference does a decent job of summarizing all the standardese here (Refer to [temp.local], [basic.lookup], and [basic.scope.class])
Is it possible to declare a templated class in C++ along with the classes it inherits from? Basically I want to give the compiler a hint, that my templated class will always inherit another at declaration time.
Maybe some code will clear up why this is a problem for me:
template<typename T>
class GrandparentClass
{
public:
T grandparentMember;
};
//this needs to be only a declaration, since I do not want classes of ParentClass with random T
template<typename T>
class ParentClass : public GrandparentClass<T>
{
};
// this does not work:
//template<typename T>
//class ParentClass : public GrandparentClass<T>;
// this does not either, because then the child class cannot access the variable from the grandparent class
//template<typename T>
//class ParentClass;
template<>
class ParentClass<int> : public GrandparentClass<int>
{
public:
ParentClass()
{
grandparentMember = 5;
}
};
template <typename T>
class ChildClass : public ParentClass<T>
{
public:
void foo()
{
std::cout << grandparentMember << "\n";
}
};
Also, I cannot use C++ 11.
EDIT:
I found an easy way out of this:
template<typename T>
class ParentClass : public GrandparentClass<T>
{
public:
ParentClass() { ParentClass::CompilerError(); };
};
Just do not define CompilerError() method in the class and everything's fine.
A class declaration is only really useful for non-value variable declarations, like pointers and references. You can't access the class members or even instantiate it, though. Even if you knew that a declared class inherits from some other one, you still wouldn't necessarily be able to utilize that information in any way.
As such, it's only important for the compiler to know what the class inherits from once it learns its full definition.
After clarification in comments: if you want to prevent instantiation of a class template with some types, its definition is the place to do it. A simple static_assert inside the class body will do the trick; Boost.StaticAssert or older SFINAE tricks will do the job for pre-C++11 code.
If you are happy with delaying the error to link-time, rather than compile time, you can declare all the member functions of parent in parent.h, provide definitions in parent.cpp, and explicitly instantiate the finite list of classes that you want.
Parent.h
template<typename T>
class ParentClass : public GrandparentClass<T>
{
ParentClass();
};
class ParentClass<int>;
class ParentClass<long int>; // or whatever
Parent.cpp
template <typename T>
ParentClass::ParentClass() : grandparentMember(5) {}
In Java, there is a detailed generic class hierarchy for containers. Java defines interfaces like ICollection<T> which is inherited by ISet<T> which is inherited by IList<T> and implemented by ArrayList<T>. I would like to create a similar hierarchy in a C++ library I am creating.
Using C++ templates however, makes this very cumbersome. For example, say I define an ISet<T>:
template<typename T>
class ISet
{
public:
virtual ~ISet() = 0;
virtual void add(T e) = 0;
virtual size_t size() = 0;
virtual bool isEmpty()
{
return size() == 0;
}
};
Then, if I wanted to make a List<T> which implements ISet<T>, I would have to list in the class definition every method that I wanted to inherit but not override, in order to let me later call it without something messy like alist::ISet<T>->isEmpty():
template<typename T>
class List : public ISet<T>
{
public:
...
void add(T e)
{
...
}
virtual sz size()
{
...
}
using ISet<T>::isEmpty; //well this is annoying
};
I understand the reason for this, and "why doesn't this work the way I expect it to?" has been answered in these qeustions: here and here.
My question is, is there a clean (or even any!) way to achieve this without having to explicitly list every inherited but not overridden method in the base class?
What I would really like would be something I could put in List<T> like:
using ISet<T>::*;
which would make all of the methods in ISet<T> dependent in the class definition of List<T>, and would alias them to List<T>::functionName.
Please tell me there is SOME way to achieve this without having to update every inheriting class's list of using directives each time I change one of my templated interfaces!
Do I have to resort to a preprocessor define of using directives defined along with the interface? Arrrrgghhhh!
This statement is incorrect:
... would have to list in the class definition every method that I
wanted to inherit but not override, in order to let me later call it
without something messy like alist::ISet->isEmpty():
Try to compile following code:
template<class T>
class Base {
public:
virtual void f1();
virtual void f2();
};
template<class T>
class Derived : public Base<T> {
public:
virtual void f1();
};
void foobar()
{
Derived<int> d;
d.f1();
d.f2();
}
If you mean that you want to access base class methods or members on derived class, you can simply do that more explicit way:
template<class T>
class Derived : public Base<T> {
public:
virtual void f1() { this->f2(); }
};
That is not messy and works as you asked, just little bit more explicit (some says it is good idea to always use this-> explicitly).
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ Inherited template classes don't have access to the base class
I'm experiencing problems with templates and inheritance. Simply, I have a template class which I want another template class to inherit from. I don't understand why members of base class are not visible within deriving class? Though without using templates everything works as expected. For example:
template <typename T>
class Foo
{
public:
T x;
T y;
void doX(){ x = x+1; }
void doY(){y++;}
protected:
T a;
T b;
void doA(){a++;}
};
template <typename T>
class Bar : public Foo<T>
{
public:
void doX(){x++; y++;} // ERROR
void doY(){x++; y++;} // ERROR
void doA(){a++;b++;} // ERROR
};
These variables are dependent names (read The Dreaded Two-Phase Name Lookup for details), so you need to use this as:
void doX(){ this->x++; this->y++; }
Usually this-> is not required as it is implicit. But here it is required. Actually explicit this-> tells the compiler to look up the name in the second phase when the base class is instantiated, as this case uses two-phase name lookup mechanism.
Or you could qualify them with base class as:
template <typename T>
class Bar : public Foo<T>
{
typedef Foo<T> base; //add this friendly typedef!
public:
void doX(){ base::x++; base::y++;}
//...
};
In this case, the fact that the names cannot be looked-up untill base (which is a typedef of Foo<T>) is instantiated, becomes more obvious (to humans eyes) in my opinion.
If the base class depends on a template parameter, then its members aren't directly available in the derived class definition. Until the template is instantiated, the compiler doesn't know what the base class will contain, and so it won't look up any names from there.
You can force it to treat the names as members by qualifying them:
void doX(){this->x++; Foo<T>::y++;} // OK: both forms specify that it's a member
Write this->x, this->y instead of x, y in derived class functions.
Try referring to the variables using the base class scope:
Foo<T>::x
or use this
this->x
I am using code::blocks, with, I believe gcc. Given the example code (this is pseudo code and may not replicate the problem):
//Assume this is in a separate header file to B
class TestA
{
protected:
int A;
public:
void Function1(){A = 0;}
};
class TestB : public TestA
{
public:
void CallFunction(){ A = 10; Function1();}//
};
I would get similar compile errors, like:
Error: 'A' not declared in this scope.
Error: Function1() not declared in this scope.
I was under the impression that all base variables and functions were inherited to the subclass. Given the base class has a lot of functions and variables, I don't want to use the 'using' keyword as I'd have to declare it for every function and variable (to my knowledge).
Is there any way to make it so TestB explicitly or actually includes the stuff it's inheriting?
Relevant snippets below
Okay. It's not possible to include example code as it's in project, but I will quote the key snippets:
C:\Users\user\Desktop\Projects\RND2\TemplateListAdv.h|30|error: 'Size' was not declared in this scope|
The line this is on is:
if(!Array.SetToSize(Size))
The class it's in is:
template<typename TemplateItem>
class TemplateListAdv : public TemplateList<TemplateItem>
And the incriminating line from TemplateList is:
SIZE_TYPE Size; //SIZE_TYPE is unsigned long.
//SIZE_TYPE is available in all files as unsigned long.
Files go:
TemplateList.h->TemplateBasics.h->TemplateListAdv.h
No missing files from what I can see.
I will tack in, the 'using' keyword resolves it individually, but this has been bugging me as I thought inheritance was automatic.
Compiler data as requested:
"Release 10.05 rev 6283 (2010-05-27 09:09:13) gcc 4.4.1 Windows/unicode - 32 bit"
So it looks like you are getting error wite template classes inheritance, isn't it? They are a big difference comparing to non-template ones. Assuming you have code like this:
template <class T>
class TestA
{
protected:
int A;
public:
void Function1(){A = 0;}
};
template <class T>
class TestB : public TestA<T>
{
public:
void CallFunction(){ A = 10; Function1();}//
};
The issue is caused by two-phase name lookup. All members of the base TestA class are dependent names, i.e. they depend on the template argument T. This is so because you can have template specialization for TestA with totally different members, e.g.:
template <class T>
class TestA
{
protected:
int A;
public:
void Function1(){A = 0;}
};
template <class T>
class TestB : public TestA<T>
{
public:
void CallFunction(){ A = 10; Function1();}//
};
template <>
class TestA<int>
{
};
Now, there is no A and Function1 members in the TestA, so they would be unaccessible in TestB as well. In order to let compiler know that these members are indeed depende on the template argument you should write TestB like this:
template <class T>
class TestB : public TestA<T>
{
public:
void CallFunction(){ this->A = 10; this->Function1();}//
};
This way you make compiler resolve names only during template instantiation time instead of template declaration time and it will known about base class members.
One thing to add is that there is no such issue with VC compiler, it doesn't try to parse templates until instantiation and thus don't support two-phase name lookup.
The problem that you're having about accessing base class stuff in a class template, is a FAQ item.
Rather then quoting the whole FAQ item here, I just link to it: that's your answer.
The code that you presented to illustrate the problem was unrelated, sorry. It is always a good idea to give an actual example rather than an example of what one thinks might be the problem.
Cheers & hth.,
The problem is that you are using templates, and the base class is a 'dependent name'. That is, the template base class could be specialized and not have the Size member, the compiler just doesn't know when it compiles your class, because the Size reference is not in a dependent context.
In your particular case the easiest solution is to refer to the inherited members using this:
if(!Array.SetToSize(this->Size))
And since this is a dependent name, it should work
Are you sure that :
Size is a protected or public attribute of TemplateList ?
you're not calling if(!Array.SetToSize(Size)) from a static method ?
The question is really bad, and you might want to improve on that. Anyway, my crystal ball tells me that Size is defined in a base template, and that because the identifier Size is not dependent lookup is not going into the base template and the compiler not seeing it. Add a this-> before Size and you should be set.
When interpreting a template member function, the compiler must (following the standard) decide for each symbol if it is dependent on the template parameter. If it is dependent on it, then it'll only be resolved when the template is instantiated. However, he must resolve it at this moment.
In your case, the compiler think that A and Function1 don't depend on the template parameter and should thus be resolvable just after the parse. You just have to make it depend on the template parameter by using this->A and this->Function1
So, you should have something like that.
template < typename T >
class Base
{
protected:
int A;
public:
void Function1() { A = 0; }
};
template < typename T >
class Derived : public Base< T >
{
public:
void CallFunction1() {
this->A = 10;
this->Function1();
}
};