I have a base class First and a derived class Second. In the base class there's a member function create and a virtual function run. In the constructor of Second I want to call the function First::create, which needs access to the implementation of its child class' run() function. A colleague recommended using function templates since First can't know it's child classes explicitly. Sounds weird? Here's some code:
First.h
#pragma once
#include <boost/thread/thread.hpp>
#include <boost/chrono/chrono.hpp>
class First
{
public:
First();
~First();
virtual void run() = 0;
boost::thread* m_Thread;
void create();
template< class ChildClass >
void create()
{
First::m_Thread = new boost::thread(
boost::bind( &ChildClass::run , this ) );
}
};
First.cpp
#include "First.h"
First::First() {}
First::~First() {}
Second.h
#pragma once
#include "first.h"
class Second : public First
{
public:
Second();
~Second();
void run();
};
Second.cpp
#include "Second.h"
Second::Second()
{
First::create<Second>();
}
void Second::run()
{
doSomething();
}
I'm getting an error at First::create<Second>(); saying Error: type name is not allowed. So what's the reason for this error? I assume I didn't quite get the whole mechanics of templates, yet - I'm very new to this topic.
Although you could use CRTP as "suggested" by Kerrek SB and Arne Mertz, here's a solution using a member function template:
class First
{
public:
First();
~First();
virtual void run() = 0;
boost::thread* m_Thread;
// vvvvvvvvvvv this declares a non-template member function `create`
void create(); // (better remove it)
// vvvvvvvvvv this declares a member function template `create`
template< class ChildClass >
void create();
};
For templates, you should provide the definition in the header file, since the definition must be available in every TU where it is required (and not only in one).
The easiest way to do this is to provide the definition of member function templates or members of class templates within the class itself:
class First
{
public:
/* ... */
template< class ChildClass >
void create()
{
// AFAIK, the `bind` is not required
First::m_Thread = new boost::thread(&ChildClass::run,
static_cast<ChildClass*>(this));
}
};
Now, if you want to call this member function template in the Second class, you'd have to explicitly provide the template argument:
void Second::any_function()
{
create<Second>();
}
Some other (possible) issues with your code:
You don't have virtual dtors, therefore deleting a pointer to a base class subobject will invoke UB.
There needs to be a downcast, as &ChildClass::run is of type void (Second::*)().
create is called inside the ctor of Second, which will call Second::run (or whatever template argument you provide), the final override of that function in the class Second. If you override that function in a class derived from Second, that override won't be called in the ctor of Second.
Your dtor of First should either detach or join the boost thread, otherwise std::terminate will be called if the thread is still running when the dtor is called.
run doesn't have to virtual in this example, the exact same code would work w/o run being virtual or even declared in First.
First you have to put template definitions in the header, or the linker will have trouble finding the instantiated templates.
Second: now the pun's done, I assume you derived Second from First<Second>. This is called the "Curiously Recurring Template Pattern" (CRTP).
Since the base class is already specialized and has the type of the derived class carved into its type, there is no need to make any function of it a template (you didn't), and the base class' functions can be just called, without specifying template parameters:
template <class SubClass>
struct First {
void create() {
SubClass& sub = static_cast<SubClass&>(*this);
mThread = make_unique<std::thread>( [&](){sub.run();} );
}
};
struct Second : First<Second> {
Second() { create(); }
void run();
};
Some annotations:
You need not qualify accesses inside First
You can just call create, it's an inherited method, and since Second is no template, there is no need to add qualification or help the compiler with the lookup.
prefer std::thread over boost::thread, it has been in the standard for a while now.
prefer std::unique_ptr over raw pointers with ownership
I prefer lambdas over bind - reads more clear to me.
I made the two classes struct in order to have the member functions public by default and save one line in the example code. There is no difference to class except that.
Related
I am trying to allow a child class to define the variadic function specialization. For example:
#include <iostream>
#include <vector>
#include <memory>
class BaseClass
{
public:
BaseClass() {};
virtual ~BaseClass() {};
template<typename GenericData>
void ReceiveData(GenericData &inData)
{
throw std::runtime_error("Undefined");
}
};
class ReceiveInt : public BaseClass
{
void ReceiveData(int & inData)
{
std::cout << "I know what to do!";
}
};
int main(int argc, char* argv[])
{
std::vector<std::shared_ptr<BaseClass>> classHolder;
classHolder.push_back(std::make_shared<ReceiveInt>());
int test = 1;
classHolder.front()->ReceiveData(test);
return 0;
}
But unfortunately this does not work, as the BaseClass ReceiveData function is called. Is this even possible?
EDIT 1
As people have pointed out, I'm very wrong with my notation. Looks like I learned more than I expected today.
Is this even possible?
I don't think so.
Dynamic dispatch is possible only for virtual member functions.
Member function templates may not be virtual.
If you can use regular member functions, i.e. not member function templates, then you can make them virtual. That will work.
You confuse some notions here.
To start with, there are no variadic templates here as ReceiveData function below:
template<typename GenericData>
void ReceiveData(GenericData &inData)
{
throw std::runtime_error("Undefined");
}
is a template member function.
Then, if you want to override a method in the derived class, the right way is to use virtual functions, probably a pure virtual function in the base class and a virtual function with an override specifier in the derived class.
However, virtual functions limit you to a a set of fixed types because there are no template virtual functions. You could experiment with CRTP though:
template<typename T>
class Base {
public:
void receiveData(const T&) {}
};
class ReceiveInt : public Base<int> {};
which emulates a sort of static polymorphism. Below:
ReceiveInt{}.receiveData(int{});
receiveData from the base class instantiated with int.
I think you may be confusing your terminology. BaseClass::ReceiveData is a templated method, taking a template parameter GenericData. A variadic function takes a number of arguments determined at runtime.
In ReceiveInt, you're not making a specialization of anything, because ReceiveInt::ReceiveData is not a templated method. In fact, even if it was templated, it would not be possible to call in your example. How would a pointer to BaseClass know how to call a template specialization in the derived class it points to?
You can make BaseClass::ReceiveData virtual. This allows you to override it in a base class, and still call it with a pointer to BaseClass. Unfortunately, templates are a compile time language feature, whereas dynamic dispatch is a runtime feature -- in this context, you can't have both.
References
Variadic Functions
Template Specialization
Why do we need virtual functions in C++?
You would have to cast to the derived type first, it is not possible using a base class pointer/reference as the base class will only know about its own implementation. This is not even a case where you can use a recursive dependency on the derived type as the derived type is not defined yet at the point the base is being instantiated.
If you do cast to the derived type then it would be able to resolve the derived member as you desire.
There is no variadic templates in your code like already explained by the others.
But you can use the fact that the templated class methods are instantiated at the first time invoked. But there is no virtual overriding here.
In this example you can define the different implementations of the method templates in Base and Derived classes, but you have explicitely tell the compiler which one to use.
It's not possible to use Derived class method through a Base class pointer without explicit cast:
#include <iostream>
#include <memory>
using namespace std;
class Base
{
public:
Base() {};
virtual ~Base() {};
template<typename T>
void ReceiveData(T)
{
throw std::runtime_error("Undefined");
}
};
class Derived : public Base
{
public:
template<typename... Args >
void ReceiveData(Args... args)
{
(void)std::initializer_list<int>{(std::cout << args << std::endl, 0)...};
}
};
int main()
{
Base b;
// b.ReceiveData(1); //-> this calls base class method
Derived d;
d.ReceiveData(1); // this calls the method in the derived class
d.ReceiveData(2, "hello"); // this calls the method in the derived class
Base* b2 = new Derived();
// b2->ReceiveData(3); // this will instantiate and call the base class method
// thus raising an exception
// because no virtual overriding of templated methods
((Derived*)b2)->ReceiveData("world",1); // this will instantiate and call the derived class
// method, then because of explicit casting the
// compiler knows which class to target
return 0;
}
Live demo: https://wandbox.org/permlink/K0qEAC7C7yzg6gYL
I have a virtual function that is implemented in a base class A.
This function has a loop in it. A derived class B is available but does not override the virtual function as the code is the same for any derived class.
Well, however, I need an additional condition check inside that virtual function (local_policy) that should be called depending on class type (base or derived).
Now, I could implement another virtual member function and override it in the derived class however as the call happens inside of a loop the virtual overhead should be minimized, so I thought I rather use a function template and specialize it for any derived classes.
Now the problem is that I am passing *this pointer to the function template from within foo() and the specialization is never called.
Is the this pointer in this certain case of type A instead of B? I would have guessed it is not and that my specialised function template would be called.
I appreciate any help!
template < typename T >
bool local_policy(const T* mtype) { return true; }
class A
{
public:
virtual void foo()
{
for(..) {
if(local_policy(this)) //This will call the non-specialised template! Why?
{ /* do something */ }
}
}
/* [...] */
}
class B : public A
{
/* [...] */
//foo() is not overridden here
}
//Specialize the function template for class B
template <>
bool local_policy(const B* mtype) { return false; }
main()
{
B* test = new B; if(!B) return;
test->foo();
}
Thanks in advance!
Best
P.S.: I also tried some C++11 using a normal function and a global template with std::enable_if to only enable if it is a derived class. Doesn't matter, also that one is not called as I expected. :-/
C++ does not allow dynamic dispatch based on argument types -- function overload resolution is always based on the static type of the expression. In your example, the static type of this with always be A *, even when it points at a B, so your specialized function will never be called.
If you want dynamic dispatch, you must use a virtual function, and you can only dynamically dispatch based on the this argument, never any other arguments. If you're worried about the overhead, you can hoist the dynamic call out of the loop and only call it once:
virtual bool local_policy() { return true; }
virtual void foo() {
bool policy = local_policy();
for (..) {
if (policy) {
/* do something */
}
}
}
The compiler can't ever do this optimization on its own, since it doesn't know that you'll never define a derived class that overrides the local_policy function with something that has side effects...
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.
I made a class with virtual function f() then in the derived class I rewrote it like the following f(int) why can't I access the base class function throw the child instance ?
class B{
public:
B(){cout<<"B const, ";}
virtual void vf2(){cout<<"b.Vf2, ";}
};
class C:public B{
public:
C(){cout<<"C const, ";}
void vf2(int){cout<<"c.Vf2, ";}
};
int main()
{
C c;
c.vf2();//error should be vf2(2)
}
You have to do using B::vf2 so that the function is considered during name lookup. Otherwise as soon as the compiler finds a function name that matches while traversing the inheritance tree from child -> parent -> grand parent etc etc., the traversal stops.
class C:public B{
public:
using B::vf2;
C(){cout<<"C const, ";}
void vf2(int){cout<<"c.Vf2, ";}
};
You are encountering name hiding. Here is an explanation of why it happens ?
In C++, a derived class hides any base class member of the same name. You can still access the base class member by explicitly qualifying it though:
int main()
{
C c;
c.B::vf2();
}
You were caught by name hiding.
Name hiding creeps up everywhere in C++:
int a = 0
int main(int argc, char* argv[]) {
std::string a;
for (int i = 0; i != argc; ++i) {
a += argc[i]; // okay, refers to std::string a; not int a;
a += " ";
}
}
And it also appears with Base and Derived classes.
The idea behind name hiding is robustness in the face of changes. If this didn't exist, in this particular case, then consider what would happen to:
class Base {
};
class Derived: public Base {
public:
void foo(int i) {
std::cout << i << "\n";
}
};
int main() {
Derived d;
d.foo(1.0);
}
If I were to add a foo overload to Base that were a better match (ie, taking a double directly):
void Base::foo(double i) {
sleep(i);
}
Now, instead of printing 1, this program would sleep for 1 second!
This would be crazy right ? It would mean that anytime you wish to extend a base class, you need to look at all the derived classes and make sure you don't accidentally steal some method calls from them!!
To be able to extend a base class without ruining the derived classes, name hiding comes into play.
The using directive allows you to import the methods you truly need in your derived class and the rest are safely ignored. This is a white-listing approach.
When you overload a member function in a base class with a version in the derived class the base class function is hidden. That is, you need to either explicitly qualify calls to the base class function or you need a using declaration to make the base class function visible via objects of the derived class:
struct base {
void foo();
void bar();
};
struct derived: base {
void foo(int);
using base::foo;
void bar(int);
};
int main() {
derived().foo(); // OK: using declaration was used
derived().bar(); // ERROR: the base class version is hidden
derived().base::bar(); // OK: ... but can be accessed if explicitly requested
}
The reason this is done is that it was considered confusing and/or dangerous when a member function is declared by a derived function but a potenially better match is selected from a base class (obviously, this only really applies to member functions with the same number of arguments). There is also a pitfall when the base class used to not have a certain member function: you don't want you program to suddenly call a different member function just because a member function is being added to the base class.
The main annoyance with hiding member functions from bases is when there is a set of public virtual functions and you only want to override one of them in a derived class. Although just adding the override doesn't change the interface using a pointer or a reference to the base class, the derived class can possibly not used in a natural way. The conventional work-around for this to have public, non-virtual overload which dispatch to protected virtual functions. The virtual member function in the various facets in the C++ standard library are an example of this technique.
It must be something specific in my code, which I can't post. But maybe someone can suggest possible causes.
Basically I have:
class CParent
{
public:
void doIt(int x);
};
class CChild : public CParent
{
public:
void doIt(int x,int y,int z);
};
CChild *pChild = ...
pChild->doIt(123); //FAILS compiler, no method found
CParent *pParent = pChild;
pParent->doIt(123); //works fine
How on earth?
EDIT: people are talking about shadowing/hiding. But the two versions of doIt have different numbers of parameters. Surely that can't confuse the compiler, overloads in child class which can't possibly be confused with the parent class version? Can it?
The compiler error I get is:
error C2660: 'CChild::doIt' : function does not take 1 argument
You have shadowed a method. For example:
struct base
{
void method(int);
void method(float);
};
struct derived : base
{
void method(int);
// base::method(int) is not visible.
// base::method(float) is not visible.
};
You can fix this with a using directive:
class derived : public base
{
using base::method; // bring all of them in.
void method(int);
// base::method(int) is not visible.
// base::method(float) is visible.
};
Since you seem insistent about the number of parameters, I'll address that. That doesn't change anything. Observe:
struct base
{
void method(int){}
};
struct derived : base
{
void method(int,int){}
// method(int) is not visible.
};
struct derived_fixed : base
{
using base::method;
void method(int,int){}
};
int main(void)
{
{
derived d;
d.method(1, 2); // will compile
d.method(3); // will NOT compile
}
{
derived_fixed d;
d.method(1, 2); // will compile
d.method(3); // will compile
}
}
It will still be shadowed regardless of parameters or return types; it's simply the name that shadows. using base::<x>; will bring all of base's "<x>" methods into visibility.
You are hitting a classic problem. You need using CParent::doIt; in your CChild class. I'll scrounge up the duplicate questions.
Edit:
Here's my answer to essentially the same question: Overriding a Base's Overloaded Function in C++
I have never done this without having that method in the base class before. I think that adding "using CLASS::METHOD" in derived class will give you access to the other version of the overloaded method.
class CParent
{
public:
void doIt(int x);
};
class CChild : public CParent
{
public:
void doIt(int x,int y,int z);
using CParent::doIt;
};
The problem is CChild doesn't actually inherit from CParent.
And so it doesn't have a doIt method that takes only one argument.
When you override a function in the derived class, only that function in the derived class is visible to the user of that class. The base class version becomes hidden.
Therefore, your pChild pointer calling doIt(int x) will fail since you are using a derived class pointer to call the base class function. The pParent pointer calling doIt(int x) will work since you are using a base class pointer to call the base class function. Even though you have a child object being pointed to by a parent pointer (upcasted), the class type here is determined by the declaration of the pointer which is a CParent.
To be able to call that base class function using the derived class pointer, you can:
Qualify the base class name in the function call, as in the following:
pChild->CParent::doIt(123);
Use a using directive to bring the function name from the base class into the derived class, as seen in the previous posts.
I understand that this behavior is to give you flexibility to override the behavior of base class method in your derived class.
Lets assume that you have a function foo(int) in base class and you want to change the behavior of this function in your derived class. Now if the base class method is not hidden by your derived class method (which has same prototype as that of base class's method), it will introduce ambiguity in overload resolution.
The method in your child class has a different number of arguments than what you're trying to pass into it. Could it be related to that?