I have a questions about C++ templates. More specifally, by using template arguments for inheritance.
I am facing strange behaviour in a closed-source 3rd party library. There is a C method
factoryReg(const char*, ICallback*)
which allows to register a subclass of ICallback and overwrite the (simplified) methods:
class ICallback
{
public:
virtual void ENTRY(void* data) = 0;
virtual void EXIT(void* data) = 0;
const char* getName() { return _name; } const
ICallback(const char* name) : _name(name) {}
virtual ~ICallback() {}
private:
const char* _name;
};
I have
class BaseCallback : public ICallback
{
public:
BaseCallback(const char* name) : ICallback(name) {}
virtual void ENTRY(void* data) {
std::cout << "in ENTRY base" << std::endl;
}
virtual void EXIT(void* data) {
std::cout << "in EXIT base" << std::endl;
};
class SpecialCallback : public BaseCallback
{
public:
SpecialCallback(const char* name) : BaseCallback(name) {}
virtual void ENTRY(void* data) {
// actually, it's 3rd party code too - assumed to do something like
...
BaseCallback::ENTRY();
}
// no redecl. of EXIT(void* data)
};
template <typename Base>
TemplCallback : public Base
{
public:
TemplCallback(Base& myT) : Base(myT.getName()), _myT(myT)
virtual void ENTRY(void* data) {
std::cout << "in ENTRY templ." << std::endl;
_myT.ENTRY();
}
virtual void EXIT(void* data) {
std::cout << "in EXIT templ." << std::endl;
_myT.EXIT();
}
private:
Base& _myT;
}
Upon registering
SpecialCallback spc("validName");
TemplCallback<SpecialCallback> myCallback(spc);
factoryReg(spc.getName(), &myCallback);
...
// output: "in ENTRY base"
// "in EXIT base"
the callback somehow does not work (debug output not being put out // breakpoints do not apply).
If I omit implementation of the EXIT(void* data) method in my template class TemplCallback - everything works fine!
// output: "in ENTRY templ."
// "in EXIT base"
Is this expected behaviour? I have been told it might be an issue of the MSVC compiler 13.10.6030 I use. Not sure about that.
BTW: The template idea presented here might not be the best choice for whatever I am trying to do ;)
But I am still interested in the matter itself, regardless about design questions.
I suspect that factoryReg doesn't actually invoke the callback, but stores the pointer and invokes the callback when something happens.
If that is the case, then this code:
TemplCallback<SpecialCallback> myCallback(spc);
factoryReg(spc.getName(), &myCallback);
causes factoryReg to store pointer to a temporary, which will go out of scope as soon as your registration function returns. Thus, when the callback is invoked, the object is not alive and you have undefined behaviour.
Your TemplCallback class looks funny. I don't think you actually want it to use a different object, but to invoke the inherited versions of ENTRY and EXIT:
template <class Base>
class TemplCallback : public Base
{
public:
TempCallback(const char* name) : Base(name)
{}
virtual ENTRY(void* data)
{
// do special processing
Base::ENTRY(data);
}
virtual EXIT(void* data)
{
// do special processing
Base::EXIT(data);
}
};
OK, it seems that it is safe to assume that SpecialCallback::ENTRY() calls BaseCallback::EXIT() somehow.
Can't be 100% sure, because it's closed source - but it's quite likely.
So much for "callback" functions...
Related
How can I access data of the mother class from a child class without creating an instace?
I've got something like:
#include <iostream>
class mother {
private:
public:
mother(){}
virtual ~mother(){}
virtual void func() const {std::cout << "mother " << dat <<std::endl;}
virtual void dat_set(std::string arg){dat=arg;}
std::string dat;
};
class child:mother {
public:
child(){}
~child(){}
void dat_set(std::string const arg) override { mother::dat_set(arg); }
void func() const override { std::cout << "child " << mother::dat << std::endl; }
};
int main (void) {
auto tmp = new mother();
tmp->dat_set("test");
auto foo = new child();
foo->func();
}
How do I make sure that func() invoked by foo gets access to the data stored in mother?
EDIT
Should I not be able to make std::string dat a static std::string dat? I tried that but I get compiler errors along the lines of
/tmp/ccZV7Y4n.o: In function `child::func()':
main.cpp:(.text._ZN5child4funcEv[_ZN5child4funcEv]+0x1d): undefined reference to `mother::dat[abi:cxx11]'
The trick to accessing functions inside base classes from derived classes is to redeclare them using virtual and override specifiers...
First, make the destructor virtual... (Since your compiler doesn't want virtual functions inside a class without a virtual destructor)
virtual ~mother() = default; // If the compiler is happy, we all are happy...
And then make your functions virtual...
virtual void dat_set(std::string const arg) { dat = arg; }
virtual void func() const { std::cout << "mother " << dat << std::endl; }
You have to define it again inside the child class since the child cannot become the mother, and that is the reason you cannot access those functions...
void dat_set(std::string const arg) override { mother::dat_set(arg); }
void func() const override { mother::func(); }
Here you have to have the exact same declaration you had in the base class (except virtual which is redundant when override is used...) and add override specifier that re-declares the same function you had in the base class inside the child class...
For behavior just put mother::func() (mother::dat_set(/*params go here*/) for calling the function with parameters, and I bet you might already know that) to call the respective function...
Note: The override specifier (since C++11) is similar to the virtual specifier, except that it is only usable in dervied classes/structures, and makes the usage of virtual inside child declarations optional (In your base class you have to use virtual instead)...
Edit: You can assign a derived class to a base class but it is not possible to do the opposite, and that is the reason why your code fails... A close attempt to doing something like this would be the usage of namespaces, for example:
namespace some_namespace
{
static std::string dat;
// The child and mother class declarations and other things go here...
}
Kind regards,
Ruks.
I am learning c++ and would like to build something similar to C# events to handle interrupts in an embedded c++ project.
So far I came up with a solution that does almost what I want. However I need some help with polymorphism (?). The following code snippet is kind of a minimum example to reproduce my situation:
#include <iostream>
struct Event
{ };
struct EventHandler
{
virtual void Esr (const Event& I) { }
};
struct EventSender
{
EventSender (EventHandler& Handler) : _Handler (Handler) { }
template <typename T>
void SendEvent (const T&) const
{
_Handler.Esr (T ());
}
EventHandler& _Handler;
};
struct SpecialEvent : public Event
{ };
struct MyHandler : public EventHandler
{
void Esr (const Event& I) override { std::cout << "Event" << std::endl; }
void Esr (const SpecialEvent& I) { std::cout << "SpecialEvent" << std::endl; }
};
int main()
{
MyHandler handler;
EventSender sender (handler);
/* Invoke directly */
handler.Esr (Event ());
handler.Esr (SpecialEvent ());
/* Invoke indirectly */
sender.SendEvent (Event ());
sender.SendEvent (SpecialEvent ()); // Expected cout msg: "SpecialEvent"
return 0;
}
Expected console output:
Event
SpecialEvent
Event
SpecialEvent
Actual console output:
Event
SpecialEvent
Event
Event
What does the compiler/linker here that I am not aware of?
Here you're trying to use overloading, not classic (virtual function based) polymorphism.
What you want (at least as I understand it) is behavior that's essentially the same between using a handler directly, and invoking it indirectly via a sender. The variation that happens is between an Event and a SpecialEvent.
That being the case, classic polymorphism would involve a virtual function in Event that's overridden in SpecialEvent:
struct Event {
virtual void operator()() const { std::cout << "Event\n"; }
};
struct SpecialEvent : public Event {
virtual void operator()() const override { std::cout << "Special Event\n"; }
};
With this in place, a reference (or pointer) to an Event will invoke the member for the actual type. Doing the polymorphism here means we only need one handler class, so the code ends up something like this:
#include <iostream>
struct Event {
virtual void operator()() const { std::cout << "Event\n"; }
};
struct EventHandler {
void Esr(const Event& I) const { I(); }
};
struct EventSender {
template <typename T>
void SendEvent (const T& t) const {
handler.Esr(t);
}
EventHandler handler;
};
struct SpecialEvent : public Event {
virtual void operator()() const override { std::cout << "Special Event\n"; }
};
int main() {
EventHandler handler;
EventSender sender;
/* Invoke directly */
handler.Esr (Event ());
handler.Esr (SpecialEvent ());
/* Invoke indirectly */
sender.SendEvent (Event ());
sender.SendEvent (SpecialEvent ()); // Expected cout msg: "SpecialEvent"
}
You have two methods in MyHandler. One of them overrides the base class method
The other one does not.
One solution would be to declare both methods in the base class:
struct EventHandler
{
virtual void Esr (const Event& I) = 0;
virtual void Esr (const SpecialEvent& I) = 0;
};
That way the compiler can use the type of the argument to resolve the method at the EventHandler level.
If you wanted to avoid the requirement that all derived classes must overload both methods you could do something like this:
struct EventHandler
{
virtual void Esr (const Event& I) = 0;
virtual void Esr (const SpecialEvent& I)
{
// if not overridden, use the non-specialized event handler.
Esr(reinterpret_cast<const Event &>(I));
}
};
To answer your question:
What does the compiler/linker here that I am not aware of?
In C++ a method call is resolved at compile/link time into either 1) a call to a particular block of code (the method body), or 2) an indirect call via a hidden data structure called a vtable. The actual vtable is determined at runtime, but the compiler has to decide which entry in the table to use for the call. (Google vtable for lots more information about what they are and how they are implemented.)
It has to base this resolution on what it's allowed to know. In this case based on the type of the pointer or reference through which the method is called. Note this is NOT necessarily the type of the actual object.
In your case when you call throgh handler the compiler is allowed to know about both methods declared in MyHandler so it can pick the one you expect, but when the call goes through sender, it has to find a method declared in EventSender. There's only one method declared in EventSender. Fortunately the argument can be coerced into a const Event & so the compiler is able to use that method. Thus it uses the vtable entry for that method. So it finds the vtable for MyHandler [at runtime] and uses the vtable entry for
Esr (const Event& I)
and that's how you end up in the wrong method.
BTW: My answer is intended to explain what you are seeing and give you a way to fix your immediate problem. Jerry Coffin's answer gives you an alternative approach that should work better for you in the long term.
First of all, you cannot cast references to a descendant of a base class.
You'll need to use a pointer to that type, and using dynamic_cast.
So, you have
EventSender sender (handler);
in main(). The constructor of sender binds to the base class of MyHandler which is EventHandler, since this is the parameter type in the constructor of MyHandler (= EventHandler::EventHandler). Therefore, EventHandler.Esr(const Event &) is called, which happens to be virtual, so there is a pointer to MyHandler.Esr(const Event &).
Note that technically, Esr(const Event &) and Esr(const SpecialEvent &) are two different methods; they just happen to use the same name.
The Non-virtual Interface idiome (NVI) is pretty self explanatory: You don't write public virtual functions, but public functions that call a private virtual implementation function, like so:
class Object{
virtual void v_load();
public:
void load(){ v_load(); }
}
This enables you, the base class author, to check and enforce pre- and post-conditions or apply other functions so the author of deriving classes can't forget about them.
Now when you are the deriving author, you may want to write a base class yourself - let's call it Pawn - that extends on the functionality of load() and therefore has to override v_load(). But now you are facing a problem:
When you override v_load(), other clients that want to derive from your class, will always overwrite that behaviour, and they can not call Pawn::v_load() because it is a private function, neither can they call Pawn::load() because it is defined as { v_load; } in Object which will of course lead to an infinite loop. Additionally, requiring them to do so could lead to mistakes when they forget that call. If I would want them to enable that, I would have to specify the acces to v_load() as protected in Object, which seems like an ugly solution as it would weaken the encapsulation of Object greatly.
You could of course still override v_load() to call a new function v_pawnLoad(), which is then overridden by clients, but that seems very error-prone as a lot of clients will probably overload the wrong function.
So, how can I design Pawn in such a way that clients can still override v_load() while keeping the ability to check pre-conditions or call other functions and (if possible) not enabling, let alone requiring clients of Object or Pawn to call the base v_load() implementation?
If your intention is to allow people to "extend" as opposed to "replace" load's behaviour, then put the code you currently have in v_load in load then call an empty v_load in the end.
Or you could just make v_load protected if you want to let people choose between "replacing" or "extending".
If you just want to allow them to replace the behaviour, your code is fine as it is.
As a bonus, in all these 3 variants you can change "allow" with "force" by making your v_load a pure virtual if you have no default behaviour.
If you wish to limit the override to your Pawn child class, add the final keyword to v_load in Pawn and use another virtual function to allow children of Pawn to customise its behaviour.
How about mixin' in some CRTP?
#include <iostream>
class BaseObject
{
private:
virtual void v_load() = 0;
public:
void load() { v_load(); }
};
template<typename Derived>
class Object : public BaseObject
{
private:
virtual void v_load() { static_cast<Derived&>(*this).load(); }
};
class Pawn : public Object<Pawn>
{
public:
void load() { std::cout << "Pawn::load()" << std::endl; }
};
class BlackPawn : public Pawn
{
private:
virtual void v_load() {
std::cout << "BlackPawn::v_load()" << std::endl;
std::cout << "- "; Pawn::load();
}
public:
void load() {
std::cout << "BlackPawn::load()" << std::endl;
std::cout << "- "; Pawn::load();
}
};
class BigBlackPawn : public BlackPawn
{
private:
virtual void v_load() {
std::cout << "BigBlackPawn::v_load()" << std::endl;
std::cout << "- "; BlackPawn::load();
}
public:
void load() {
std::cout << "BigBlackPawn::load()" << std::endl;
std::cout << "- "; BlackPawn::load();
}
};
template<typename T>
void load(T& x)
{
x.load();
}
void vload(BaseObject& x)
{
x.load();
}
int main()
{
Pawn p;
BlackPawn bp;
BigBlackPawn bbp;
load(p);
load(bp);
load(bbp);
std::cout << std::endl;
vload(p);
vload(bp);
vload(bbp);
}
Output on ideone.
Summary: In search of the standard C++ design pattern for loading different files via constructor
I have a Base class with some functionality that will be used by all derived classes (e.g. Derived_A, Derived_B). The principal difference is that Derived_A and Derived_B override the load function, which is used by the constructor to load a data file (load may also be called explicitly outside the constructor).
I ran into an unexpected problem from this: the load function called by the constructor treats the class as the Base type, but when I use a default constructor and call the load function explicitly, then the virtual function table permits the intended load function to be called.
This smells like a classic problem, but I can't figure out a way to do it (and I was most recently programming in Python, which I believe, due to weak typing, would always call the intended function).
In the same vein, I'd really like Base::load to be pure virtual / abstract (only derived classes will be instantiated); however, that won't compile (I believe, because the compiler sees that the pure virtual function will be called).
Can you help?
Output:
Loading w/ constructor:
Base::load file_A
Base::load file_B Loading w/ function post construction:
Derived_A::load file_A
Derived_B::load file_B
Code:
#include <iostream>
#include <string>
class Base
{
public:
Base() {}
Base(std::string x)
{
load(x);
}
virtual void load(std::string x)
{
std::cout << "\tBase::load " << x << std::endl;
}
};
class Derived_A : public Base
{
public:
Derived_A() {}
Derived_A(std::string x): Base(x) {}
void virtual load(std::string x)
{
std::cout << "\tDerived_A::load " << x << std::endl;
}
};
class Derived_B : public Base
{
public:
Derived_B() {}
Derived_B(std::string x): Base(x) {}
void virtual load(std::string x)
{
std::cout << "\tDerived_B::load " << x << std::endl;
}
};
int main()
{
// simpler code, but it doesn't behave as I hoped
std::cout << "Loading w/ constructor:" << std::endl;
Base*der_a = new Derived_A(std::string("file_A"));
Base*der_b = new Derived_B(std::string("file_B"));
// this is what I want to do
std::cout << "Loading w/ function post construction:" << std::endl;
der_a = new Derived_A;
der_a->load( std::string("file_A") );
der_b = new Derived_B;
der_b->load( std::string("file_B") );
return 0;
}
The behavior you see is well defined in C++ -- it's just not useful in this scenario because the class is not fully constructed when you call load(std::string) from Base::Base(std::string).
There are two immediate approaches:
A
You could use a container type which calls load (and perhaps holds on to the string as well). This may be more practical if you need to hold on to instances (e.g. they may have specialized error information).
class Loader
{
public:
Loader(Base* const p, const std::string& location) : d_base(p)
{
this->d_base->load(location);
}
private:
std::unique_ptr<Base>d_base;
private:
Loader(const Loader&) = delete;
Loader& operator=(const Loader&) = delete;
};
In use:
std::cout << "Loading w/ Loader:\n";
Loader l_der_a(new Derived_A, "file_A");
Loader l_der_b(new Derived_B, "file_B");
B
You could also approach it using a helper function:
class Base {
public:
template<typename T>
static void Load(const std::string& x)
{
T().load(x);
}
Base()
{
}
Base(std::string x)
{
/* load(x); << see Load(const std::string&) */
}
virtual ~Base()
{
}
virtual void load(std::string x) = 0;
};
In use:
std::cout << "Loading w/ Base::Load<T>():\n";
Derived_A::Load<Derived_A>("file_A");
Derived_B::Load<Derived_B>("file_B");
And then there are several other approaches and variations - it depends on what fits your design best. With C++, you certainly have options.
You can look up "Named Constructor Idiom".
I'm trying to implement an event manager based on the linked code in the top answer here:
Game Objects Talking To Each Other
However I'm getting an error when I try to register the callbacks.
I'm sure it has to do with the typedef, and I admit I'm not sure how it works exactly, but it is in the exact same form in the linked code.
The B class should be inherriting from the Interface, so why is the type different?
I've condensed the code into the smallest example below.
#include <iostream>
class Interface;
typedef void (Interface::*Callback)(void *data);
class Interface
{
public:
void Register (Callback func);
};
void Interface::Register(Callback func)
{
std::cout << "Register" << std::endl;
}
class B : public Interface
{
public:
B();
void Echo(void *data);
};
B::B()
{
Register( (Callback)Echo );
}
void B::Echo(void *data)
{
std::cout << "Echo" << std::endl;
}
int main()
{
B b;
return 0;
}
Here's the error I get under g++ 4.6.1:
test.cpp: In constructor ‘B::B()’:
test.cpp:31:22: error: argument of type ‘void (B::)(void*)’ does not match ‘Callback {aka void (Interface::*)(void*)}’
Could anyone please explain what I'm doing wrong?
Thanks
As #Kerrek correctly pointed out, Echo is not a member of Interface, therefore B::Echo doesn't qualify as Interface::*Callback. But you can use a template to accomplish that, e.g.:
template <class T> class Interface {
public:
typedef void (T::*Callback)(void *data);
void Register(Callback func) {
std::cout << "Register" << std::endl;
}
// ...
};
class B : public Interface<B> {
public:
B() {
Register(&B::Echo);
}
void Echo(void *data) {
// Do something
}
};
I think you might be better off using std::function (c++11) or boost::function (c++03+boost)
#include <iostream>
class Interface;
typedef void (Interface::*Callback)(void *data);
class Interface
{
public:
std::function<void(void*)> register;
Interface(std::function<void(void*)> register_)
: register(register_) //intializer list
{}
virtual ~Interface(){} //put me in
};
void Interface::Register(Callback func)
{
std::cout << "Register" << std::endl;
}
class B : public Interface
{
public:
B();
void Echo(void *data);
};
B::B()
: Interface( std::bind(B::Echo, this) )
{}
void B::Echo(void *data)
{
std::cout << "Echo" << std::endl;
}
Although why you aren't using pure virtuals is beyond me
class Interface
{
public:
virtual void Echo(void*)=0;
};
void B::Echo(void *data) //implements Echo
{
std::cout << "Echo" << std::endl;
}
call interface->echo will call the child
if you need performance then use the
http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
And be very careful with void* they are generally considered bad.
EDIT ADDRESSING POINT IN COMMENTS: non pure virtuals
class Interface
{
public:
virtual ~Interface(){} //put me in
virtual void echo(void*){} //if implementation is not extended it will do nothing.
//others
};
This ins't Java, interfaces aren't a thing defined by the language. This way you can have an interface which you can pick can choose which part to implement, if a callback doesn't concern your class, then just don't implement it.
void* are bad for a whole host of reasons. from C++ FAQ
avoid void* (keep them inside low-level functions and data structures
if you really need them and present type safe interfaces, usually
templates, to your users)
http://www2.research.att.com/~bs/bs_faq.html
search on "void*"
but basically void* bypass all the type safety that C++ went out of it's way adding. It is a hack in C to make up for the fact that it doesn't have any polymorphism or generic code.