The following C++ code produces compilation errors.
The compiler (gcc 5.2.0) complains that at line 15 it cannot find matching function for call to 'Derived::test_func()'; yet if test_func() is moved from Base to Derived, it compiles without error.
class Base {
public:
int test_func();
};
class Derived : public Base {
public:
template <typename T>
int test_func(T t);
};
template <typename T>
int Derived::test_func(T t)
{
test_func(); // line 15
return 0;
}
int Base::test_func()
{
return 0;
}
If the template function calls other functions in the Base class with different names (not the same name as the template function), as the following code shows, it also compiles fine.
class Base {
public:
int test_func_diff_name();
};
class Derived : public Base {
public:
template <typename T>
int test_func(T t);
};
template <typename T>
int Derived::test_func(T t)
{
test_func_diff_name();
return 0;
}
int Base::test_func_diff_name()
{
return 0;
}
Why is this? What is the constraints specified in C++ in calling base functions from templates? Can someone point me to some resources?
In C++, functions in derived classes which don't override functions in base classes but which have the same name hide all other functions with the same name in the base class.
It is usually preferable to give different functions different names.
If you really need it, you can call the base class' function by fully qualifying the name, like Base::test_func();
Or explicitly introduce the base class' names into the current class with using Base::test_func;
Related
I have the following code:
template <typename T>
class A {
public:
virtual void func() {
// Things that don't use T parameter.
}
};
class B : public A<int> {
public:
void func() {
A<int>::func();
// Working...
}
};
Basically, I want to override a virtual function defined in a class template from inside a class that inherits from a specialized version of such template (A).
Does this work in C++? Is it good practice? Also, is it ok to call the overridden method as I did in the overriding one? (please, note that, for compatibility with the toolchain I'm using, this is C++98)
Thank you.
I have a class template that implements a number of functions. I want to be able to also add specialized version of this class which has only a few functions that override those of the base, when a specific type is declared. I know I could achieve this with a class template and explicit specializations of it. However I also want to:
Have the explicit specializations uniquely named, similar to how a base and derived class are uniquely named.
Call the Base functions from an instantiated Derived object, either inside a Derived function, or explicitly as below with obj1.Foo
This is the (simplified) example code I am trying to make work:
In myClasses.h
template<typename T>
class Base
{
public:
void Foo (T& input);
virtual void Bar (T& input);
}
template<>
class Derived : public Base<int>
{
public:
void Bar (int& input) override;
}
In myClasses.cpp
template<typename T>
Base::Foo(T& input) { // Do something generic }
template<typename T>
Base::Bar(T& input) { // Do something generic }
template<>
Derived::Bar(int& input) { // Do something int-dependent }
In main.cpp
int main()
{
Base<int> obj1 = new Derived();
obj1.Foo(input); // Runs Base::Foo
obj1.Bar(input); // Runs Derived::Bar
}
However this code fails with the explicit specialization of non-template Derived error, among others. I've read a lot of StackOverflow threads to get me this far, but I haven't found any that have helped me make this compile. So my questions are:
Is combining class templates with class inheritance possible in this way?
Why does the compiler label the Derived class a non-template despite me explicitly using that keyword?
What is the correct syntax that will make this code work? (assuming what I am trying to do is possible)
EDIT: Following the suggesting of HTNW, I can turn Derived into a regular class by removing the template<> prefix. This will allow everything to compile up to obj1.Foo(input). It seems that the instantiated Derived class can't find or access the base Foo function.
Thanks to ravnsgaard and HTNW for the helpful suggestions which got me to a solution. The key was to remove the template<> keyword from the Derived class (because I wanted it to be a class and not a class template) and declaration of Base<int> at the end of the source file. So the working code looks like this:
In myClasses.h
template<typename T>
class Base
{
public:
void Foo (T& input);
virtual void Bar (T& input);
}
class Derived : public Base<int>
{
public:
void Bar (int& input) override;
}
in myClasses.cpp
template<typename T>
Base::Foo(T& input) { // Do something generic }
template<typename T>
Base::Bar(T& input) { // Do something generic }
Derived::Bar(int& input) { // Do something int-dependent }
template class Base<int>; // VERY IMPORTANT.
In main.cpp
int main()
{
Base<int> &&obj1 = Derived();
obj1.Foo(input); // Runs Base::Foo
obj1.Bar(input); // Runs Derived::Bar
}
In particular, without the template class Base<int>; declaration at the end of myClasses.cpp, the call to obj1.Foo will fail with an error complaining that Derived has no such function.
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;
}
};
i have a c++ class like the below one working at vc++ , but doesnt work anymore in linux gcc 4.7. And i have no idea how to make it work again.
test.h
template<typename a>
class test: public a
{
public:
void fun();
};
test.cpp
template<typename a>
void test<a>::fun()
{
template_class_method(); <-- this is a public method from template_class
}
template class test<template_class>;
template_class.h
class template_class {
public:
template_class();
virtual ~template_class();
void template_class_method();
};
template_class.cpp
#include "templateclass.h"
template_class::template_class() {
// TODO Auto-generated constructor stub
}
template_class::~template_class() {
// TODO Auto-generated destructor stub
}
void template_class::template_class_method() {
}
You need to qualify it with the base class name as:
a::template_class_method();
The qualification a:: is necessary because template_class_method exists in a. The C++ rule is that if the base is a class template or template argument, then all its members are not automatically visible to the derived classes. In order to help the compiler to find the member, you need to tell it to look for the member in the base class, for which you need to qualify the member which is of the form of base::member_function() or base::member_data.
In your case, since the base is a, and the member is template_class_method, so you have to write this:
a::template_class_method();
Note that such a base class is called dependent base class since it depends on the template argument.
I don't know why #Karthik T deleted the answer, but that answer was on the right path. You have several options
Use qualified name a::template_class_method()
template<typename a>
class test : public a
{
public:
void fun()
{
a::template_class_method();
}
};
Use class member access syntax this->template_class_method()
template<typename a>
class test : public a
{
public:
void fun()
{
this->template_class_method();
}
};
Make the base class method visible through using-declaration
template<typename a>
class test : public a
{
public:
using a::template_class_method;
void fun()
{
template_class_method();
}
};
Note that the first method will suppress the virtuality of template_class_method (in cases when it is virtual), so it should be used with caution. For this reason, method number 2 is preferred, since it preserves the natural behavior of template_class_method.
Your comment stating that this->template_class_method() "doesn't work" is unclear. It works without any problems. Moreover, as I said above, this is in general case a better option than using a qualified name.
In CRTP to avoid dynamic polymorphism, the following solution is proposed to avoid the overhead of virtual member functions and impose a specific interface:
template <class Derived>
struct base {
void foo() {
static_cast<Derived *>(this)->foo();
};
};
struct my_type : base<my_type> {
void foo() {}; // required to compile. < Don't see why
};
struct your_type : base<your_type> {
void foo() {}; // required to compile. < Don't see why
};
However it seems that the derived class does not require a definition to compile as it inherits one (the code compiles fine without defining a my_type::foo). In fact if a function is provided, the base function will not be called when using the derived class.
So the question is, is the following code replacement acceptable (and standard?):
template <class Derived>
struct base {
void foo() {
// Generate a meaningful error if called
(void)sizeof( Derived::foo_IS_MISSING );
};
};
struct my_type : base<my_type> {
void foo() {}; // required to compile.
};
struct your_type : base<your_type> {
void foo() {}; // required to compile.
};
int main() {
my_type my_obj;
my_obj.foo(); // will fail if foo missing in derived class
}
The whole point of this pattern is, as far as I understand, that you can pass arguments simply as template <typename T> base<T> & and your interface is defined by (non-virtual) functions in base<T>. If you don't have an interface that you want to define (as you are suggesting in the second part of your question), then there's no need for any of this in the first place.
Note that you are not "imposing" an interface like with pure virtual functions, but rather you are providing an interface. Since everything is resolved at compile time, "imposing" isn't such a strong requirement.
In your replacement code you can't "polymorphically" call foo on a base<T>.
However it seems that the derived class does not require a definition to compile as it inherits one (the code compiles fine without defining a my_type::foo).
C++ is lazy : it will not try to make base<my_type>::foo() if you do not actually use it.
But if you try to use it, then it will be created and if that fails, compilation errors will flow.
But in your case, base<my_type>::foo() can be instanciated just fine :
template <class Derived>
struct base {
void foo() {
static_cast<Derived *>(this)->foo();
};
};
struct my_type : base<my_type> {};
void func() {
my_type m;
static_cast<base<my_type>& >(m).foo();
}
will compile just fine. When the compiler is presented with
static_cast(this)->foo(), it will try to find a foo() that is accessible in my_type. And there is one: it's called base<my_type>::foo(), which is public from a publicly inherited class. so base<my_type>::foo() calls base<my_type>::foo(), and you get an infinite recursion.
No, imagine the following situation:
template <typename T>
void bar(base<T> obj) {
obj.foo();
}
base<my_type> my_obj;
bar(my_obj);
Base's foo will be called instead of my_type's...
Do this, and you will get your erro message:
template <class Derived>
struct base {
void foo() {
sizeof(Derived::foo);
static_cast<Derived *>(this)->foo();
};
};
But I must confess I am not sure how this will work in compilers other than GCC, tested only with GCC.