CLOS has a neat concept of :before, :after, and :around methods.
The :before methods are called before the primary method.
The :after methods are called after the primary method.
The :around methods are called around the :before+primary+:after sequence.
The :before, :after, and :around methods are chained rather than overridden. Suppose both a parent and child class define a foo method and :before foo method. The child's foo method overrides the parent's foo method, but both the child's and parent's :before foo methods are called before this overridden method is called.
Python decorators provide something similar to the CLOS :around methods. There is nothing like this in C++. It has to be hand-rolled:
class Child : public Parent {
virtual void do_something (Elided arguments) {
do_some_preliminary_stuff();
Parent::do_something (arguments);
do_some_followup_stuff();
}
};
Downsides:
This is an anti-pattern to some people.
It requires me to be explicit in specifying the parent class.
It requires extenders of my classes to follow the same paradigm.
What if I need to call the grandparent because the parent doesn't override do_something, and what about multiple inheritance?
It doesn't quite capture the CLOS concept.
I found these concepts to be quite handy way back when I used Flavors (predecessor to CLOS). I've used the above workaround in a few places, and a few have challenged it as an anti-pattern. (Others have emulated it elsewhere, so the derision is not universal.)
The question: Is this considered an anti-pattern in C++, and are there better workarounds?
You can get the basics of this quite nicely using (std/boost)::shared_ptr. For details see here : http://www.boost.org/doc/libs/1_46_1/libs/smart_ptr/sp_techniques.html#wrapper
Getting the inheritance behaviour you mention just requires the prefix/suffix functions to call the prefix/suffix functions in the parent class.
This is what I could do, but it's still a bit ugly.
Basically I put the actual work in a separate hook so you don't have call the pre/post hooks in the processing method. In the inheritance chain you have total control both on whether you want to add pre/post hooks and the ordering of the hook calls (call the parent's hook before or after the child's hook).
#include <iostream>
#define C(s) std::cout << s << std::endl;
class Parent {
public:
virtual void do_something(int arg) {
do_some_pre_hook();
do_some_hook(arg);
do_some_post_hook();
}
virtual void do_some_pre_hook() {
C("parent pre_hook");
}
virtual void do_some_post_hook() {
C("parent post_hook");
}
virtual void do_some_hook(int arg) {
//this is where you actually do the work
}
};
class Child : public Parent {
public:
typedef Parent super;
virtual void do_some_pre_hook() {
super::do_some_pre_hook();
C("Child pre_hook");
}
virtual void do_some_post_hook() {
super::do_some_post_hook();
C("Child post_hook");
}
};
class GrandChild : public Child {
public:
typedef Child super;
virtual void do_some_pre_hook() {
super::do_some_pre_hook();
C("GrandChild pre_hook");
}
virtual void do_some_post_hook() {
super::do_some_post_hook();
C("GrandChild post_hook");
}
virtual void do_some_hook(int arg) {
//this is where you actually do the work
C("GrandChild hook");
}
};
int main() {
GrandChild gc;
gc.do_something(12);
}
Note: Ideally you would use an AOP c++ compiler or compiler extension for a task like that, but the last time I tried it it wasn't quite stable...
I'm not claiming this is equivalent or comparable to what other languages do, but I think the Non Virtual Interface idiom is applicable for your problem:
class parent {
public:
void foo()
{
before_foo();
do_foo();
after_foo();
}
protected:
// you can make those pure virtual with an implentation, too
virtual void before_foo() { ... }
virtual void do_foo() { ... }
virtual void after_foo() { ... }
};
class child: public parent {
protected: // or private
void before_foo() { ... }
void do_foo() { ... }
// must provide a dummy after_foo that delegates to parent::after_foo
// if it is pure virtual in the parent class
};
When calling p.foo(), the most derived before_foo, after_foo and do_foo are always called.
Related
For example, say I have a basic data object class as below.
class DataObject {
protected:
bool data_changed;
virtual void save() {}
virtual void load() {}
public:
virtual void idle() {
if (data_changed) {
save();
data_changed = false;
}
}
};
The idea is that "idle" is called periodically from some main looping thread and performs non-critical updates.
Now I want derived classes to be able to have their own idle functions. But I don't want to lose the default behavior.
One solution is to say "remember to call DataObject::idle() from overridden idle() functions".
Like this:
class ChildData : public DataObject {
public:
virtual void idle() override {
//do something
DataObject::idle(); //remember to call parent idle!
}
};
But this is very dangerous as people can just forget.
Is there a way to enforce this somehow? Or make it automatic, like a virtual destructor?
(My current "workaround" is to have 2 functions, one the parent_idle that does the important stuff, and then one overridable child_idle that derived functions can override. But this is a bit messy, and also you have to make a whole new set of functions again if you want some child function to enforce its own default...)
Maybe you could write it:
...
void idle_start() { // not virtual, main looping thread calls this
idle();
if (data_changed) {
save();
data_changed = false;
}
}
virtual void idle() { } // virtual, noop by default
...
That depends if you want to have your derived behavior before the mandatory base behavior.
I have a problem, and I tried to use RTTI to resolve it.
I have a class Base and children classes (in the example, I show only one Child)
class Base {
virtual void Eval() {
// normal treatment
+
// treatment only for Base instance
}
};
class Child : Base {
void Eval() {
// call Base Eval
Base::Eval();
//other treatment
}
};
The problem, is that in Base::Eval, there are some treatments which I dont't want to execute when I call it from Child.
What I mean, in Child::Eval, when we call the Base::Eval, we want only the normal treatment which is executed.
For this, I thought about RTTI. I don't know if it is the best way to use it, I thought to do something like this:
class Base {
virtual void Eval() {
// normal treatment
+
if (typeid(this).name() == typeid(Base).name()) {
// treatment only for Base instance
}
}
}
The question is: Is it permitted to do that?
Am I obliged to check typeid.name()?
Or would just typeid() be enough?
Situations such as this are almost always an indication of bad design. A base class should not know anything about its derived classes.
If you want to give derived classes an option to customise parts of the base behaviour, use virtual functions and the "template method" design pattern:
class Base
{
public:
virtual void Eval() {
// normal treatment
Eval_CustomisationHook();
}
protected:
virtual void Eval_CustomisationHook()
{
// Do the stuff
}
};
class Child : public Base
{
protected:
virtual void Eval_CustomisationHook()
{} // do nothing
};
Alternatively, you could delegate just the query:
class Base
{
public:
virtual void Eval() {
// normal treatment
if (doOptionalEvalPart()) {
// do it here
}
}
protected:
virtual bool doOptionalEvalPart()
{
return true;
}
};
class Child : public Base
{
protected:
virtual bool doOptionalEvalPart()
{
return false;
}
};
And to answer your original question as well: the correct form would be to compare the std::type_info objects, not their names. And don't forget you'd have to dereference this. So the code would look like this:
if (typeid(*this) == typeid(Base))
This will do what you want it to. But as I've said above, this is most probably not the proper approach.
Let's say I have a parent class, Arbitrary, and two child classes, Foo and Bar. I'm trying to implement a function to insert any Arbitrary object into a database, however, since the child classes contain data specific to those classes, I need to perform slightly different operations depending on the type.
Coming into C++ from Java/C#, my first instinct was to have a function that takes the parent as the parameter use something like instanceof and some if statements to handle child-class-specific behavior.
Pseudocode:
void someClass(Arbitrary obj){
obj.doSomething(); //a member function from the parent class
//more operations based on parent class
if(obj instanceof Foo){
//do Foo specific stuff
}
if(obj instanceof Bar){
//do Bar specific stuff
}
}
However, after looking into how to implement this in C++, the general consensus seemed to be that this is poor design.
If you have to use instanceof, there is, in most cases, something wrong with your design. – mslot
I considered the possibility of overloading the function with each type, but that would seemingly lead to code duplication. And, I would still end up needing to handle the child-specific behavior in the parent class, so that wouldn't solve the problem anyway.
So, my question is, what's the better way of performing operations that where all parent and child classes should be accepted as input, but in which behavior is dictated by the object type?
First, you want to take your Arbitrary by pointer or reference, otherwise you will slice off the derived class. Next, sounds like a case of a virtual method.
void someClass(Arbitrary* obj) {
obj->insertIntoDB();
}
where:
class Arbitrary {
public:
virtual ~Arbitrary();
virtual void insertIntoDB() = 0;
};
So that the subclasses can provide specific overrides:
class Foo : public Arbitrary {
public:
void insertIntoDB() override
// ^^^ if C++11
{
// do Foo-specific insertion here
}
};
Now there might be some common functionality in this insertion between Foo and Bar... so you should put that as a protected method in Arbitrary. protected so that both Foo and Bar have access to it but someClass() doesn't.
In my opinion, if at any place you need to write
if( is_instance_of(Derived1) )
//do something
else if ( is_instance_of(Derived2) )
//do somthing else
...
then it's as sign of bad design. First and most straight forward issue is that of "Maintainence". You have to take care in case further derivation happens. However, sometimes it's necessary. for e.g if your all classes are part of some library. In other cases you should avoid this coding as far as possible.
Most often you can remove the need to check for specific instance by introducing some new classes in the hierarchy. For e.g :-
class BankAccount {};
class SavingAccount : public BankAccount { void creditInterest(); };
class CheckingAccount : public BankAccount { void creditInterest(): };
In this case, there seems to be a need for if/else statement to check for actual object as there is no corresponsing creditInterest() in BanAccount class. However, indroducing a new class could obviate the need for that checking.
class BankAccount {};
class InterestBearingAccount : public BankAccount { void creditInterest(): } {};
class SavingAccount : public InterestBearingAccount { void creditInterest(): };
class CheckingAccount : public InterestBearingAccount { void creditInterest(): };
The issue here is that this will arguably violate SOLID design principles, given that any extension in the number of mapped classes would require new branches in the if statement, otherwise the existing dispatch method will fail (it won't work with any subclass, just those it knows about).
What you are describing looks well suited to inheritance polymorphicism - each of Arbitrary (base), Foo and Bar can take on the concerns of its own fields.
There is likely to be some common database plumbing which can be DRY'd up the base method.
class Arbitrary { // Your base class
protected:
virtual void mapFields(DbCommand& dbCommand) {
// Map the base fields here
}
public:
void saveToDatabase() { // External caller invokes this on any subclass
openConnection();
DbCommand& command = createDbCommand();
mapFields(command); // Polymorphic call
executeDbTransaction(command);
}
}
class Foo : public Arbitrary {
protected: // Hide implementation external parties
virtual void mapFields(DbCommand& dbCommand) {
Arbitrary::mapFields();
// Map Foo specific fields here
}
}
class Bar : public Arbitrary {
protected:
virtual void mapFields(DbCommand& dbCommand) {
Arbitrary::mapFields();
// Map Bar specific fields here
}
}
If the base class, Arbitrary itself cannot exist in isolation, it should also be marked as abstract.
As StuartLC pointed out, the current design violates the SOLID principles. However, both his answer and Barry's answer has strong coupling with the database, which I do not like (should Arbitrary really need to know about the database?). I would suggest that you make some additional abstraction, and make the database operations independent of the the data types.
One possible implementation may be like:
class Arbitrary {
public:
virtual std::string serialize();
static Arbitrary* deserialize();
};
Your database-related would be like (please notice that the parameter form Arbitrary obj is wrong and can truncate the object):
void someMethod(const Arbitrary& obj)
{
// ...
db.insert(obj.serialize());
}
You can retrieve the string from the database later and deserialize into a suitable object.
So, my question is, what's the better way of performing operations
that where all parent and child classes should be accepted as input,
but in which behavior is dictated by the object type?
You can use Visitor pattern.
#include <iostream>
using namespace std;
class Arbitrary;
class Foo;
class Bar;
class ArbitraryVisitor
{
public:
virtual void visitParent(Arbitrary& m) {};
virtual void visitFoo(Foo& vm) {};
virtual void visitBar(Bar& vm) {};
};
class Arbitrary
{
public:
virtual void DoSomething()
{
cout<<"do Parent specific stuff"<<endl;
}
virtual void accept(ArbitraryVisitor& v)
{
v.visitParent(*this);
}
};
class Foo: public Arbitrary
{
public:
virtual void DoSomething()
{
cout<<"do Foo specific stuff"<<endl;
}
virtual void accept(ArbitraryVisitor& v)
{
v.visitFoo(*this);
}
};
class Bar: public Arbitrary
{
public:
virtual void DoSomething()
{
cout<<"do Bar specific stuff"<<endl;
}
virtual void accept(ArbitraryVisitor& v)
{
v.visitBar(*this);
}
};
class SetArbitaryVisitor : public ArbitraryVisitor
{
void visitParent(Arbitrary& vm)
{
vm.DoSomething();
}
void visitFoo(Foo& vm)
{
vm.DoSomething();
}
void visitBar(Bar& vm)
{
vm.DoSomething();
}
};
int main()
{
Arbitrary *arb = new Foo();
SetArbitaryVisitor scv;
arb->accept(scv);
}
I have a class (let's call it A) the inherits an interface defining several abstract methods and another class there to factor in some code (let's call it B).
The question is, I have an abstract method in the interface that A implements just to call the B version. Is there a way to use the keyword using to avoid writing a dull method like:
int A::method() override
{
return B::method();
}
I tried writing in A using B::method, but I still get an error that A doesn't implement the abstract method from the interface.
Is there a special technique to use in the case or am I just out of luck? (and if so, is there a specific reason why it should be that way?).
Thanks.
edit:
To clarify, the question is, why isn't it possible to just do this:
class A: public Interface, public B {
using B::method;
};
Let's make this clear. You basically have the following problem, right?
struct Interface
{
virtual void method() = 0;
};
struct B
{
void method()
{
// implementation of Interface::method
}
};
struct A : Interface, B
{
// some magic here to automatically
// override Interface::method and
// call B::method
};
This is simply impossible, because the fact that the methods have the same names is irrelevant from a technical point view. In other word's, Interface::method and B::method are simply not related to each other, and their identical names are not more than a coincidence, just like someone else called "Julien" doesn't have anything to do with you just because you share the same first name.
You are basically left with the following options:
1.) Just write the call manually:
struct A : Interface, B
{
virtual void method()
{
B::method();
}
};
2.) Minimise writing work with a macro, so that you can write:
struct A : Interface, B
{
OVERRIDE(method)
};
But I would strongly recommend against this solution. Less writing work for you = more reading work for everyone else.
3.) Change the class hierarchy, so that B implements Interface:
struct Interface
{
virtual void method() = 0;
};
struct B : Interface
{
virtual void method()
{
// implementation of Interface::method
}
};
struct A : B
{
};
if B::method is abstract you cannot call it because is not implemented... has no code.
An example:
class A
{
public:
virtual void method1( ) = 0;
virtual void method2( ){ }
};
class B : public A
{
public:
virtual void method1( ) override
{ return A::method1( ); } // Error. A::method1 is abstract
virtual method2( ) override
{ return A::method2( ); } // OK. A::method2 is an implemented method
}
Even if there were a way to do what you want, in the name of the readability of your code, I would not recommend that.
If you do not put the "B::" before "method" call, when I read that, I would say it is a recursive call.
Compare the following two variants (that should do the same thing)
class Foo
{
public:
void void doStuff()
{
//...
doStuffImpl();
//...
}
virtual void doStuffImpl()=0;
void affectStateInFoo()
{}
};
class Bar:public Foo
{
public:
void doStuffImpl()
{
affectStateInFoo();
}
};
And
class Foo;
class Callback
{
public:
virtual void doStuff(Foo& foo)=0;
};
class Foo
{
public:
Foo(Callback& o):obj(o){}
void void doStuff()
{
//...
obj.doStuff(*this);
//...
}
void affectStateInFoo()
{}
Callback& obj;
};
class Bar:public Callback
{
public:
void doStuff(Foo& foo)
{
foo.affectStateInFoo();
}
};
When is one of the two variants to prefer?
Your first method requires Bar to inherit from Foo, which closely couples these classes. For callbacks this is not always what you want to do. Your second method doesn't require this.
I would use the first method if you actually extending a class, but for notifications I would use the second approach, or as Igor R. mentioned in the comments a function pointer like object.
I would prefer the second one because it is more unit-testable with mocks. But that's just my opinion.
Overdoing stuff per inheritance is a common failure to newcomers of object orientation.
Using delegation, you called it callback, is in common more flexible.
Less numbers of classes
possible reuse of "callback" class
Exchangeable at runtime instead of compiletime