This question already has answers here:
C++ virtual method not called as desired
(4 answers)
Closed 5 years ago.
I have an interface from which a user derives multiple classes which I have no knowledge of but still I want to call these derived classes common method Run().
The Event class is intended to be an interface so I know how to call my unknown UserEvents derived class, since they all must have that Run() method implemented.
I currently have some code and get an error that CallEvent can't allocate an abstract Event. I understand the error, but don't know how I can go about and execute this correctly.
Here's some minimal code example (WandBox):
#include <iostream>
class Event
{
public:
virtual void Run(int Param) = 0;
};
// This is a user event and I have no idea what the class name is,
// but I still have to call it's method Run() that is common to the interface "Event"
class UserEvent : public Event
{
public:
virtual void Run(int Param) { std::cout << "Derived Event Dispatched " << Param << std::endl;};
};
// This parameter is of pure abstract base class Event because
// I have no idea what my user class is called.
void CallEvent(Event WhatEvent)
{
WhatEvent.Run(123);
};
int main()
{
std::cout << "Hello World!" << std::endl;
UserEvent mE;
CallEvent(mE);
}
I took your sample code (Like so) and tried to make it running (for illustration):
#include <iostream>
class Event {
public:
virtual void Run(int Param) = 0;
};
// This is a user event and I have no idea what the class name is,
// but I still have to call it's method Run() that is common to the interface "Event"
class UserEvent: public Event {
public:
virtual void Run(int Param)
{
std::cout << "Derived Event Dispatched " << Param << std::endl;
}
};
// This parameter is of pure abstract base class Event because
// I have no idea what my user class is called.
void CallEvent(Event *WhatEvent)
{
std::cout << "in CallEvent(Event *WhatEvent):" << std::endl;
// Huh? WhatEvent = new Event();
// wrong: WhatEvent.Run(123);
// Instead, use ->.
// For pointers, check for non-nullptr is very reasonable:
WhatEvent->Run(123);
// obsolete: delete WhatEvent;
}
// second approach using a reference (as recommended in comments):
void CallEvent(Event &WhatEvent)
{
std::cout << "in CallEvent(Event &WhatEvent):" << std::endl;
WhatEvent.Run(123); // for references - select operator . is fine
}
int main()
{
std::cout << "Hello World!" << std::endl;
/* nullptr does not make sense:
* UserEvent *mE = nullptr;
* Go back to original approach:
*/
UserEvent mE;
CallEvent(&mE); // calling the first (with Event*)
CallEvent(mE); // calling the second (with Event&)
return 0;
}
Now, it is compilable and runnable. Output:
Hello World!
in CallEvent(Event *WhatEvent):
Derived Event Dispatched 123
in CallEvent(Event &WhatEvent):
Derived Event Dispatched 123
(Life demo on ideone)
I annotated every modification in comments inside the sample code.
Related
My question is related to C++. I have two families of classes: "Floor" and "Object". The first and the second family has a virtual method named "Enter" (which is called when an object enters the floor).
I wish to distinguish the behavior of "Enter" based on the sub-class of a "Floor" and "Object" respectively.
So I overload the method "Enter" with derived classes as the parameters. I have got code that works correctly, but requires two steps to call proper method, and would like to ask whether it can be done in one function call:
Edit: I updated the code (now full working example) with the potential solution. I have used a pointer to method with casting to retrieve proper overloaded method. This pointer is initialized in the constructors of the derived "Floor" classes.
#include <iostream>
using namespace std;
class Floor;
class Flagstone;
class Object
{
public:
virtual void Enter(Floor *f); /* Generic object enters generic floor */
virtual void Enter(Flagstone *fs); /* Generic object enters flagstone */
};
class Box : public Object
{
public:
void Enter(Floor *f);
void Enter(Flagstone *fs);
};
class Floor
{
public:
typedef void (Object::*enterPtr)(Floor *);
enterPtr enter; /* Pointer to method, initialized by constructor */
Floor(enterPtr enter) : enter(enter)
{
}
};
class Flagstone : public Floor
{
public:
/* Select proper overloaded function using casting */
Flagstone() : Floor((enterPtr)(void (Object:: *)(Flagstone *))&Object::Enter)
{
}
};
void Object::Enter(Floor *f)
{
cout << " Generic object enters generic floor" << endl;
}
void Object::Enter(Flagstone *fs)
{
cout << "Generic object enters flagstone" << endl;
}
void Box::Enter(Floor *f)
{
/* Box enters generic floor */
cout << "Box enters generic floor" << endl;
}
void Box::Enter(Flagstone *b)
{
/* Executed when a Box enters Flagstone: Correct */
cout << "Box enters Flagstone" << endl;
}
int main()
{
Floor *f = new Flagstone();
Object *o = new Box();
(o->*(f->enter))(f);
return 0;
}
Could I ask you to provide a minimum, reproducible example? Copying the code as is doesn't compile; indeed, there seems to be a circular dependency between the Floor and Object classes, as both rely on each other's implementation to be defined at all!
Both me and Nathan have tried to resolve this by forward-declaring the derived subtype 'Box', but this might be moot because:
you may want to invoke Box methods from Floor::Enter and Flagstone::Enter
the compiler throws an error for 'an undefined reference to a vtable', with answers here:
I agree with the others that Object::Enter(Flagstone*) seems redundant seems redundant given there exists Object::Enter(Floor*), which can resolve the dynamic type of the pointer passed-in
I ended up just realizing that the main() in this code could be actually a virtual Object or Floor method! Proper method will be called at first place and it will know one of the objects' true class.
So I cleaned the code. The function Enter(Floor *, Item *) just calls virtual method Floor::Enter() and it delegates the control to virtual method Item::Enter(), but now with addition to overloading.
The result method just reacts for the specific Floor and Item for example: Flagstone and Box incrementing the placed boxes counter.
This is very clean solution, however I can't make the methods inline as there is a cycle dependancy. But it's not a problem.
Here is the solution code:
#include <iostream>
using namespace std;
class Floor;
class Flagstone;
class Item
{
public:
/* Overload */
virtual void Enter(Floor *fl)
{
cout << "Item enters Floor." << endl;
}
virtual void Enter(Flagstone *fs)
{
cout << "Item enters Flagstone." << endl;
}
};
class Box : public Item
{
public:
static int count;
virtual void Enter(Floor *fl)
{
cout << "Box enters Floor." << endl;
}
virtual void Enter(Flagstone *fs)
{
cout << "Box enters Flagstone. Count++" << endl;
count++;
}
};
class Cherry : public Item
{
};
class Item;
class Floor
{
public:
/* Virtual Floor method. If object is in derived class,
it will call proper method. */
virtual void Enter(Item *it);
};
class Flagstone : public Floor
{
public:
virtual void Enter(Item *it);
};
class Wall : public Floor
{
};
/* Virtual Floor method. If object is in derived class, it will call proper method. */
void Floor::Enter(Item *it)
{
/* OK, we have Floor and Item or Item sub-class now we call item method, enter */
it->Enter(this);
}
void Flagstone::Enter(Item *it)
{
/* OK, we have Flagstone */
it->Enter(this);
}
int Box::count = 0;
void Enter(Floor *fl, Item *it)
{
fl->Enter(it);
}
int main(void)
{
Floor *fl = new Flagstone;
Item *it = new Box;
Enter(fl, it);
return 0;
}
I have a IBase class and a Child class. I need to call different proc function in different child class. I'm not sure which form below is actually right, maybe neither XD.
Form 1: Exactly I don't want my IBase have any non-virtual function.
Form 2: There's a strange expression &IBase::proc could make some misunderstanding.
class IBase
{
public:
virtual void proc() = 0;
auto createBind()
{
return bind(&IBase::proc, this);
}
};
class Child :public IBase
{
public:
void proc() override
{
cout << "Hello World" << endl;
}
};
int main()
{
IBase* pointer = new Child;
//form 1
thread th(pointer->createBind());
th.join();
//form 2
thread th2(&IBase::proc, pointer);
th2.join();
cout << "Finish" << endl;
return 0;
}
I'm wondering how do you guys solve this circumstance in a real project.
The most idiomatic and robust way is probably this
std::thread t([=]{pointer->proc();});
No bind, no extraneous helper member function, no weird syntax with redundant mention of the class name.
I would use form 3 :-) :
thread* th3 = pointer->start();
th3->join();
with start in IBase as:
thread* start()
{
thread* t = new thread(createBind());
return t;
}
Which would in my opinion hide more details of the implementation and give the caller the API he expects (start a thread).
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.
I have a class called 'ValueChecker'
which has the following member function:
template<typename T>
bool ValueChecker::checkMe( std::ostringstream &oss, T &me) {
std::cout << "Default checkMe() for " << typeid(me).name() << std::endl;
return true;
}
The class ValueChecker is intended to do some simple checks on the values of derived class. checkMe() will eventually get specialized for the different derived classes:
class Airplane : public ValueChecker {
friend class ValueChecker;
[...]
}
template<>
bool ValueChecker::checkMe<Airplane>( std::ostringstream &oss, Airplane &me) {
...
/* Actually, this code is generated from a simple file which translates
* a simple language into C++ code. So that a non-developer can write
* the simple checks.
*
* ValueChecker itself has utility functions that may be called in the
* template specialization which are shared across all types.
*/
}
This works, but there's just a small problem with the declaration of checkMe, when you look at the invocation:
int main() {
Airplane plane;
std::ostringstream oss;
if( plane.checkMe( oss, plane)) {
cout << "Values are bogus! " << oss.str() << endl;
return 0;
}
I call plane.checkMe(oss,plane). But, I could just as well pass another Airplane and not check plane. Furthermore, the invocation is redundant? Meaning, theoretically, the compiler should know which template function to call based on the plane's type. There shouldn't be a need to pass it in as an argument too? Anyways, it would be nice not to eliminate the last argument. So a call like this would be nice:
if( plane.checkMe(oss)) { ... } // Calls the right template specialization.
I just can't get it to work. Can the C++ guru's here help me out? thanks.
For your given code, you don't really need to use either template or friend. Instead use inheritance, and make the checkMe() method as protected and virtual method. Then override the checkMe() method in the derived class. If you do not need a default implementation, you could as well make it pure virtual. Here's a quick code snippet based on your example. (Note the use of this pointer.)
class ValueChecker {
protected:
virtual bool checkMe() {
std::cout << "Default checkMe() for " << typeid(this).name() << std::endl;
return true;
}
};
class Airplane : public ValueChecker {
public:
virtual bool checkMe() {
std::cout << "Airplane checkMe() for " << typeid(this).name() << std::endl;
return true;
}
};
int main() {
Airplane plane;
plane.checkMe();
}
You would need a default implementation when there's some "common" logic you want to use in one or more derived classes, in addition to the logic specific to the derived class itself. In that case, use the scope resolution operator to access the base class's logic.
bool Airplane::checkMe() {
std::cout << "Airplane checkMe() for " << typeid(this).name() << std::endl;
// use the "common" logic from the base class (if required)
ValueChecker::checkMe();
return true;
}
You might want to implement this as a pure virtual method.
class ValueChecker
{
public:
virtual bool checkMe(std::ostringstream& oss) = 0;
};
class Airplane : public ValueChecker
{
public:
virtual bool checkMe(std::ostringstream& oss);
};
That way you can just call plane.checkMe(oss) and the checkMe-Method of airplane will be called.
There's a common trick that is often done: http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
that could do the trick for you.
struct TimerEvent
{
event Event;
timeval TimeOut;
static void HandleTimer(int Fd, short Event, void *Arg);
};
HandleTimer needs to be static since I'm passing it to C library (libevent).
I want to inherit from this class. How can this be done?
Thanks.
You can easily inherit from that class:
class Derived: public TimerEvent {
...
};
However, you can't override HandleTimer in your subclass and expect this to work:
TimerEvent *e = new Derived();
e->HandleTimer();
This is because static methods don't have an entry in the vtable, and can't thus be virtual. You can however use the "void* Arg" to pass a pointer to your instance... something like:
struct TimerEvent {
virtual void handle(int fd, short event) = 0;
static void HandleTimer(int fd, short event, void *arg) {
((TimerEvent *) arg)->handle(fd, event);
}
};
class Derived: public TimerEvent {
virtual void handle(int fd, short event) {
// whatever
}
};
This way, HandleTimer can still be used from C functions, just make sure to always pass the "real" object as the "void* Arg".
To some extent the traits pattern lets you inherit and redefine static methods.
First start with a base class:
struct base {
static void talk() { std::cout << "hello" << std::endl; }
static void shout() { std::cout << "HELLO !!" << std::endl; }
};
Then derive it and redefine some methods:
struct derived: public base {
static void talk() { std::cout << "goodbye" << std::endl; }
};
And now call the methods via a traits class:
template < class T >
struct talker_traits {
static void talk() { T::talk(); }
static void shout() { T::shout(); }
};
talker_traits<base>::talk() // prints "hello"
talker_traits<base>::shout() // prints "HELLO !!"
talker_traits<derived>::talk() // prints "goodbye"
talker_traits<derived>::shout() // prints "HELLO !!"
ideone demo
The traits class lets you reuse the static method base::shout while "overriding" base::talk with derived::talk. Still, there are several difference with actual inheritance:
The function to call is resolved at compile time
The child method needs not have the same signature as the parent one
It works with static fields and typedefs too, the best example is std::iterator_traits.
You've got a bit of a conflict here in your question. When you pass &TimerEvent::TimerHandler to a C library, you do exactly that. You could also have passed &DerivedTimerEvent::TimerHandler, if you wanted. But you can't pass &TimerEvent::TimerHandler and expect the C library (!) to figure out you actually meant &DerivedTimerEvent::TimerHandler.