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
Related
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) {}
This question already has answers here:
Why do I have to access template base class members through the this pointer?
(3 answers)
Closed 7 years ago.
I have a templated class that I inherit from, and access through the derived class the base class members.
I can't access them without using "this" and I find a descent reason why.
If I understand correctly, when I use a template, a copy of the templated code is being made with a specialization, and only then it compiles. Meaning if I write vector<int> the compiler makes a copy of vector and replaces all the "T" with "int".
If that is the case, I don't see why there should be any difference between templates and non-templated code.
template <typename T>
class b
{
protected:
int myMember;
};
template<typename T>
class e : public b<T>
{
public:
void dosomething()
{
this->myMember = 2; // Everything is perfect
myMember = 2; // Doesn't compile in GCC, can't find the member
}
};
int main()
{
e<int> mye;
mye.dosomething();
}
Because the base class is dependent on template parameters, the base members are not considered during unqualified lookup.
When you use this-> you use class member lookup instead, which will examine the base class members, even if it is a dependent type.
I am new to C++. During my learning phase I encountered with below issue.
I am trying to derive a class stack from a class template Queue.
Compiler throws below error in constructor of stack
..\src\TrainingDay2.cpp:44:3: error: 'b' was not declared in this scope
b=a;
Please help to find out the root cause.
#include <iostream>
using std::cout;
using std::endl;
template<class T> class Queue //Base class
{
private:
T ArrQueue[20];
protected:
T* a;
T* b;
public:
Queue() { cout<<"QUEUE CONST "<< endl; }
void push(T x);
void pop(void);
};
template <class T>
class stack :public Queue<T> // Derived class
{
public:
stack():Queue<T>() {
b=a;
}
void pop() {
b--;
}
};
int main()
{
stack<int> S;
return 0;
}
Because the base class is a template, whose instantiation depends on a template parameter of the derived class, and you're trying to name a member of the base class, two-phase lookup mandates that you write this->b, not b.
(And that default constructor call is not needed.)
stack()
{
this->b = this->a;
}
void pop()
{
this->b--;
}
(live demo)
Welcome to C++… :P
[C++11: 14.6.2/3]: In the definition of a class or class template, if a base class depends on a template-parameter, the base class scope is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member. [..]
The reason is that inside a template, two-phase name lookup rules apply:
Names which do not depend on template parameters are looked up (=resolved) when the template is defined (=parsed).
Names which do depend on template parameters are looked up when the template is instantiated (when you provide the template arguments).
Base classes which depend on template parameters are only searched during name lookup at instantiation time.
The reason for this two-phase lookup is that until the template arguments are known, the compiler cannot know what the definition of the base class (or other dependent construct) will be. Remember that template specialisation exists.
You need to somehow tell the compiler that the name b is dependent. You basically have three ways to do that:
Prefix the name with this->; since you're in a class template, all your members depend on template parameters implicitly:
this->b = a;
Use full qualification for the name. This will make the dependency on template parameters explicit:
Queue<T>::b = a;
Put a using declaration into your class to inform the compiler that the name comes from a dependent base class:
template <class T>
class stack :public Queue<T> // Derived class
{
protected:
using Queue<T>::b;
public:
stack():Queue<T>()
{
b=a;
}
void pop()
{
b--;
}
};
In a template definition, unqualified names will no longer find members of a dependent base (as specified by [temp.dep]/3 in the C++ standard). For example,
You must make the names dependent, e.g. by prefixing them with this->.
gcc-problem-using-a-member-of-a-base-class-that-depends-on-a-template-argument
And yes, it can be valid in VS.
This question already has answers here:
Why do I have to access template base class members through the this pointer?
(3 answers)
Closed 8 years ago.
I am developing a library at my work and I have designed a complicated inheritance that includes template classes and deriving from them.
My problem is that a base template class has virtual overloaded operator that takes 2 arguments and returns some value. In base class this operator is implemented and most of derived classes does not reimplement this operator.
Some other class uses derived classes for some work and make use of their operator member function. Everything works just fine as long as derived class has no other overloaded operator, even with different number of arguments. If one does then the base class operator is not accessible using it as object() because compiler can not find proper member function (complains about argument count missmatch).
It does not matter wether default template arguments for base class was specified or not. Also order of definitions of derived classes does not change which operator cause the problem (it is always SpecificDerived class).
Below I present simplified problem.
[EDIT] Example was simplified
Base Class definition:
template<class ret_t>
class TemplateBase2
{
public:
virtual ~TemplateBase2()
{
}
virtual ret_t memberFunc(ret_t x)
{
return x * 2;
}
};
User of derived classes definition:
template <class worker, class ret_t>
ret_t gobble(worker w, float f)
{
return w.memberFunc((ret_t)f);
}
Derived class:
class SpecificDerived2: public TemplateBase2<float>
{
public:
float memberFunc()
{
return 3.14;
}
};
Main function:
#include <iostream>
#include "TemplateBase2.h"
using namespace std;
int main()
{
SpecificDerived2 sd2;
cout << "sd2: " << gobble<SpecificDerived2, float>(sd2, 3.14f) << endl;
return 0;
}
Compiler exits with error claiming that there is no matching function for call to 'SpecificDerived2::memberFunc(float)' from gobble function. Problem exists only when either derived or base class has two overloaded functions of the same name, but different arguments.
I am using MinGW32 4.8.1 with c++11 support.
When a class template derives from a base class template, the base members are not visible in the derived class template definition. (This makes sense; until you specialize, there is no class, and so there are no members. Explicit specializations can always change the meaning of any given template class.)
In other words, the base template member names are dependent names and not looked up in the first phase of template definition lookup.
There are three ways to get around this. Let's make it concrete with a quick example:
template <typename T> struct Foo
{
int data;
using type = const T &;
void gobble() const;
template <int N> void befuddle();
};
template <typename T> struct X : Foo<T> { /* ... */ };
Now in the context of the derived class template definition, you can...
Qualify the name:
Foo<T>::data = 10;
typename Foo<T>::type x;
Foo<T>::gobble();
Foo<T>::template befuddle<10>();
Use this:
this->data = 10;
this->gobble();
this->template befuddle<10>();
(This doesn't work for type names names.)
Use a using declaration:
using Foo<T>::data;
using Foo<T>::gobble;
using type = typename Foo<T>::type;
data = 10;
gobble();
(This doesn't work for template names.)
Update: After your edit, the question is entirely different. Templates don't play a role at all here, since the problem doesn't contain templates, only classes. What's happening is the simple fact that member functions in a derived class hide member functions of the same name in base classes, so the presence of SpecificDerived2::memberFunc hides the base member function. The simple solution is to unhide base members of the same name with a using declaration:
class SpecificDerived2 : public TemplateBase2<float>
{
public:
using TemplateBase2<float>::memberFunc;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
float memberFunc()
{
return 3.14;
}
};
This question already has answers here:
Why do I have to access template base class members through the this pointer?
(3 answers)
accessing protected members of superclass in C++ with templates [duplicate]
(2 answers)
Closed 8 years ago.
Here is code sample which reproduces my problem:
template <typename myType>
class Base {
public:
Base() {}
virtual ~Base() {}
protected:
int myOption;
virtual void set() = 0;
};
template <typename InterfaceType>
class ChildClass : public Base < std::vector<InterfaceType> >
{
public:
ChildClass() {}
virtual ~ChildClass() {}
protected:
virtual void set();
};
template <typename InterfaceType>
void ChildClass<InterfaceType>::set()
{
myOption = 10;
}
My usage in main():
ChildClass<int> myObject;
I get the following error (gcc 4.4.3 on ubuntu):
‘myOption’ was not declared in this scope
If my ChildClass would be without new template parameter this would work fine, i.e.:
class ChildClass : public Base < std::vector<SomeConcreteType> >
Edit
I've managed to solve it, if my set method looks like:
Base<std::vector<InterfaceType> >::myOption = 10;
It works fine. Still though not sure why I need to specify all template parameters.
myOption is not a dependent name, i.e. it doesn't depend on the template arguments explicitly so the compiler tries to look it up early. You must make it a dependent name:
template <typename InterfaceType>
void ChildClass<InterfaceType>::set()
{
this->myOption = 10;
}
Now it depends on the type of this and thus on the template arguments. Therefore the compiler will bind it at the time of instantiation.
This is called Two-phase name lookup.
C++03 14.6.2 Dependent names
In the definition of a class template or a member of a class template,
if a base class of the class template depends on a template-parameter,
the base class scope is not examined during unqualified name
lookup either at the point of definition of the class template or
member or during an instantiation of the class template or member.
The following code should work.
template <typename InterfaceType>
void ChildClass<InterfaceType>::set()
{
Base<std::vector<InterfaceType> >::myOption = 10;
}