Overriding C++ function based on conditional - c++

So I've used C for a long time and Java, too, but I'm not that familiar with C++. The situation is that we have:
base class template 1 -> base class template 2 -> several relevant subclasses
Currently all of the final subclasses inherit a member function from class 1, but we need to change the behavior of this function only in one of the subclasses, and only if a variable elsewhere in the code is set, and otherwise run the function as defined in class 1. Is there a way to do this without slotting the entire function definition on the other side of an if-else? I've looked at SFINAE/enable-if, but that's used for type-based decisions, not simple conditionals like this.
If I'm missing anything easy or dumb please let me know.
Some pseudocode might help:
template <class Face> class Publisher {
virtual void publish(...) {
// do stuff
}
}
template <class NewsType> class NewsPublisher : public Publisher<OnlineFace> {
// constructors, destructors...
}
class MagazinePublisher : public NewsPublisher<Sports> {
void publish(...) {
if(that.theOther() == value) {
// do different stuff
} else {
// do whatever would have been done without this override here
}
}
}

According to your example you can simply call the base class implementation explicitly:
class MagazinePublisher : public NewsPublisher<Sports> {
void publish(...) {
if(that.theOther() == value) {
// do different stuff
} else {
// call the base class implementation, as this function would not
// have been overridden:
NewsPublisher<Sports>::publish(...);
// ^^^^^^^^^^^^^^^^^^^^^^^
}
}
}
Well, I suppose your actual base class function publish() is declared as virtual member.
Also since your sample is just pseudo code and I couldn't really test it, you might need to add which publish() implementation should be used in the NewsPublisher<T> class:
template <class NewsType> class NewsPublisher : public Publisher<OnlineFace> {
public:
// constructors, destructors...
using Publisher<OnlineFace>::publish(); // <<<<<<<<<<<<<
}

Related

How can I easily redirect a Base method to an identical Derived class method?

In working with a framework (Godot) that uses a register_method(<name>, <pointer_to_method>) to register a c++ method to a scripting API.
this method however doesn't support pointer to template classes.
So in the example:
static void _register_methods() {
register_method("my_method", &TMyClass::my_method); // this fails
// ^ template class
register_method("my_method", &MyClass::my_method); // this works
// ^ normal class
}
I have a template class TExample and an Example that extends the template class. The methods declarations and method definitions are all inside the TExample (however the methods are registered in Example).
So when I do:
register_method("my_method", &Example::my_method); // this fails because it is referencing the method of the parent class (template).
What I've found that works is redirecting the methods to "local" methods.
class Example : TExample<...>
{
public:
void my_method() {
TExample::my_method();
}
static void _register_methods() {
register_method("my_method", &Example::my_method); // this works
}
}
But imagine I have like 50 methods every time I want to create a new class from the template I need to redirect 50 methods. is there a shortcut to do this?!
Not sure what you mean by "this fails".
It just works, look (live demo):
template<class T>
class TExample {
public:
void my_method() {}
};
class Example : TExample<int> {
template<class U>
static void register_method(U u) {
}
public:
static void register_methods() {
register_method(&Example::my_method); // it works
register_method(&TExample::my_method); // this also works
}
};
int main()
{
Example ex;
ex.register_methods();
}
Now if you want to access my_method() from outside the class, then you should inherit publicly:
class Example : public TExample<...>
{
Then Example::my_method() will also work outside.
Note: TExample is not a template class, but a class template. However, in the context of a template instantiation (inside the definition of Example) the template arguments are substituted automatically.
Since template classes will be created for the types you are using you should mention the type also.
register_method("my_method", &TMyClass<Type>::my_method);
What about using a lambda ?
Does:
register_method("my_method", [&obj](*whateverParam*) { obj.templateMethod(*whateverParam*); } );
work?
(assuming obj contains the actual method, but that could be replaced by any instance containing the method).

Pass parent class reference as argument in derived class in C++

I'm new to C++ and am trying to achieve the following design.
class A { do (); doMore (); } // abstract
class B { do (); doMore (); } // abstract
class X : public A, public B // Also abstract
{
foo() {
// common code
A::do();
A::doMore();
}
bar() {
// common code
B::do();
B::doMore();
}
}
Both A and B provide implementations of do() and doMore().
How can I extract the common code that the new function takes an arg that calls the method in the correct parent class?
Something like
X::newMethod(arg_that_indicates_parent_class) {
// common code
arg_that_indicates_parent_class::do();
arg_that_indicates_parent_class::doMore();
}
Then call it like so
newMethod(pass_A_somehow);
newMethod(pass_B_somehow);
Looks like runtime polymorphism, but not quite (or is it?)... as it is within a child class...
Is this design itself just trash and there is a better way to achieve this?
If the idea is that do and doMore will be present in both A and B and those are the functions specifically you wish to call, you could
use a template function like so:
class X : public A, public B // Also abstract
{
template <typename T>
void newMethod()
{
T::do();
T::doMore();
}
}
Then using it explicitly, you could then do it like so:
X x;
x.newMethod<A>();
x.newMethod<B>();
This has the added benefit of catching some errors at compile time, that is, if you try and pass a C and it does not have
the do and doMore functions defined, you will receive a complier error (instead of a run-time crash).
This also lets you utilize the std::enable_if functionality if you are using C++1x.
Hope that can help.
Just factor out the "common code", and make it, well, common:
class X : public A, public B // Also abstract
{
void foo() {
commoncode();
A::do();
A::doMore();
}
void bar() {
commoncode();
B::do();
B::doMore();
}
void commoncode()
{
// Your common code
}
}
That's the most simple, straightforward way. Another alternative way would be closer in line to your "pass me a pointer of some kind" intended approach:
class X : public A, public B // Also abstract
{
void call_a()
A::do();
A::doMore();
}
void call_b()
B::do();
B::doMore();
}
void commoncode( void (X::*ptr)() )
{
// Your common code
(this->*ptr)();
}
}
And the parameter to commoncode() would be either
&X::call_a
or
&X::call_b

How to obtain similar result as virtual function template c++

Here's my issue, I'm trying to create a base class which can get a reference to a queue member in a derived class. I have two template functions in my base class :
class Base
{
template<TYPE type>
virtual void foo(std::queue<TYPE>*& typeQueue) //I know virtual isn't allowed
{
//do nothing as it's general case
}
template<typename TYPE>
void bar(TYPE type)
{
std::queue<TYPE>* typeQueue;
foo(typeQueue);
//... do some stuff with type
}
}
and a derived class which would theoretically be able to specialize the function foo for any types
class Derived : public Base
{
public:
template<>
void foo<int>(std::queue<int>*& m_integerQueue)
{
integerQueue= &m_integerQueue;
}
template<>
void foo<double>(std::queue<double>*& doubleQueue)
{
doubleQueue = &m_doubleQueue;
}
private:
std::queue<int> m_integerQueue;
std::queue<double> m_doubleQueue;
}
code above is more of about an ideology then a code to take word for word, I'd like the function bar to call the according function foo in derived class based on the type specified when bar is called. Of course this solution isn't working and the problem here is that we can't make template functions virtual.
I'm not sure if it's an error of design, but that's the general idea and I couldn't find an appropriate solution anywhere so I posted my own question here.
EDITED to make my problem clear

oop - C++ - Proper way to implement type-specific behavior?

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);
}

Templates as an alternative to virtual functions in C++

I have an expensive function defined in a base class, which depends on low level information from its derived classes:
class BaseClass{
...
// Defined in derived class
virtual int low_level(int)=0;
// Expensive function depending on the pure virtual function
void myExpensiveFunction(){
for(...){
for(...){
for(...){
... = low_level(...);
...
}
}
}
}
};
class DerivedClass : public BaseClass{
// A very cheap operation that can be inlined:
inline virtual int low_level(int i){
return a[i];
}
// Calling the base class function
void test(){
myExpensiveFunction();
}
};
If I understand things correctly, the fact that the low-level function is virtual prevents it from being inlined in the code above. Now, I was thinking about a way to get around this and thought of the following solution, where I pass a pointer to the derived class member function as a template parameter:
class BaseClass{
...
// The function is now templated by the derived function:
template<typename D, int (D::*low_level)(int)>
void myExpensiveFunction(){
for(...){
for(...){
for(...){
... = static_cast<D*>(this)->low_level(...);
...
}
}
}
}
};
class DerivedClass : public BaseClass{
// A very cheap operation that can be inlined:
inline int low_level(int i){
return a[i];
}
// Calling the base class function
void test(){
myExpensiveFunction<DerivedClass,&DerivedClass::low_level>();
}
};
Does this strategy make sense? I imagine that the low level operation will be inlined when the expensive base class function is expanded in the derived class.
I tested implementing it and it compiles and works, but I haven't seen any noticeable differences in performance.
Kind regards,
Joel
Passing the function you want to call using a pointer to member to a base class doesn't really improve over using a virtual function. In fact, I would expect it to make the situation worse. An alternative approach is to use a function object with an inline function call operator and call this. The "normal" approach is to kind of invert the class hierarchy and use the Curiously Recurring Template Pattern: the idea is to create a template which will derive from its template argument. The template argument is expected to provide the customization points, e.g. the function low_level.
Depending on the situation, you could also try to avoid inheritance altogether and do something like this instead:
template<typename LL>
class HighLevel {
LL lowLevel;
public:
HighLevel(LL const &ll) : lowLevel(ll) { }
void myExpensiveFunction() {
for(...) {
for(...) {
for(...) {
... = lowLevel.low_level(...);
...
}
}
}
}
};
class LowLevel {
public:
inline int low_level(int i) { // note: not virtual
return a[i];
}
};
Used like:
HighLevel<LowLevel> hl;
hl.myExpensiveFunction();
If you don't want different types of HighLevel<...> objects floating around, you could derive all those from an abstract, non-template class HighLevelBase which exposes a virtual void myExpensiveFunction() = 0 that gets implemented in the template.
Whether or not this makes sense for your situation, I cannot tell without more information, but I find that C++ often offers better tools than inheritance to solve particular problems.