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
Related
I use a third party library over which I have no control. It contains 2 classes A and B, which both define a method with the same name:
class A {
public:
...
void my_method ();
};
class B {
public:
...
void my_method ();
};
I want to create a class C that contains a member which is of class A or B. Crucially, I can know only at runtime whether I will need A or B. This class C will only call the method my_method.
If I could modify the code, I would simply make A and B derive from a parent class (interface) that defined my_method. But I can't.
What is the simplest/most elegant way to create this class C? I could of course define C in this way:
class C {
public:
void call_my_method() { if (a) a->my_method() else b->my_method(); }
private:
A* a;
B* b;
But I want to avoid paying the cost of the if statement everytime. It also feels inelegant. Is there a way I can create a super type of class A or B? Or any other solution to this problem?
You may use std::function (not sure it has better performance though), something like:
class C {
public:
void call_my_method() { my_method(); }
void use_a(A* a) { my_method = [=]() { a->my_method() }; }
void use_b(B* b) { my_method = [=]() { b->my_method() }; }
private:
std::function<void()> my_method;
};
No; at some point you need branching. The best you can do is to hoist the branching up/down the call stack†, so that more of your program is encapsulated within the figurative if/else construct and the branch itself need be performed less frequently. Of course then you need to duplicate more of your program's source code, which is not ideal.
The only improvement I'd suggest at this time is a construct such as boost::variant. It basically does what you're already doing, but takes up less memory and doesn't have that layer of indirection (using what's called a tagged union instead). It still needs to branch on access, but until profiling has revealed that this is a big bottleneck (and you'll probably find that branch prediction alleviates much of this risk) I wouldn't go any further with your changes.‡
† I can never remember which way it goes lol
‡ One such change might be to conditionally initialise a function pointer (or modern std::function), then call the function each time. However, that's a lot of indirection. You should profile, but I'd expect it to be slower and harder on the caches. An OO purist might recommend a polymorphic inheritance tree and virtual dispatch, but that's not going to be of any use to you once you care about performance this much.
How about using inheritance with a virtual function, using a 'base class' (C):
class C
{
public:
virtual void do_method() = 0;
};
class D : public C, private A
{
void do_method() { my_method(); }
};
class E : public C, private B
{
void do_method() { my_method(); }
}
Then this will work:
C * d = new D();
d->do_method();
Suggest to wrap your A and B objects into some helper template TProxy which realizes IProxy interface. Class C (or Consumer) will work with IProxy interface and won't know about type of the object inside Proxy
#include <stdio.h>
struct A {
void func () { printf("A::func\n"); }
};
struct B {
void func () { printf("B::func\n"); }
};
struct IProxy
{
virtual void doFunc() = 0;
virtual ~IProxy() {};
};
template<typename T>
struct TProxy : public IProxy
{
TProxy(T& i_obj) : m_obj(i_obj) { }
virtual void doFunc() override { m_obj.func(); }
private:
T& m_obj;
};
class Consumer
{
public:
Consumer(IProxy& i_proxy) : m_proxy(i_proxy) {}
void Func() { m_proxy.doFunc();}
private:
IProxy& m_proxy;
};
Main:
int main()
{
A a;
TProxy<A> aProxy(a);
B b;
TProxy<B> bProxy(b);
Consumer consumerA{aProxy};
consumerA.Func();
Consumer consumerB{bProxy};
consumerB.Func();
return 0;
}
Output:
A::func
B::func
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(); // <<<<<<<<<<<<<
}
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.
I was wondering whether there's a way to override a function for a specific instance only. For ex,
class A
{
public:
...
void update();
...
}
int main()
{
...
A *first_instance = new A();
// I want this to have a specific update() function.
// ex. void update() { functionA(); functionB(); ... }
A *second_instance = new A();
// I want this to have a different update() function than the above one.
// ex. void update() { functionZ(); functionY(); ...}
A *third_instance = new A();
// ....so on.
...
}
Is there a way to achieve this?
I think virtual function is just what you want, with virtual function, different instances of the same type can have different functions, but you need to inherit the base class. for example
class A
{
public:
...
virtual void update()
{
std::cout << "Class A\n";
}
...
};
class B: public A
{
public:
virtual void update()
{
std::cout << "Class B\n";
}
};
class C: public A
{
public:
virtual void update()
{
std::cout << "Class C\n";
}
};
int main()
{
...
A *first_instance = new A();
// I want this to have a specific update() function.
// ex. void update() { functionA(); functionB(); ... }
A *second_instance = new B();
// I want this to have a different update() function than the above one.
// ex. void update() { functionZ(); functionY(); ...}
A *third_instance = new C();
// ....so on.
...
}
each instance in the above code will bind different update functions.
Besides, you can also use function pointer to implement your requirement, but it is not recommended. For example
class A
{
public:
A(void(*u)())
{
this->update = u;
}
...
void (*update)();
};
void a_update()
{
std::cout << "update A\n";
}
void b_update()
{
std::cout << "update B\n";
}
void c_update()
{
std::cout << "update C\n";
}
int main()
{
...
A first_instance(a_update);
// I want this to have a specific update() function.
// ex. void update() { functionA(); functionB(); ... }
A second_instance(b_update);
// I want this to have a different update() function than the above one.
// ex. void update() { functionZ(); functionY(); ...}
A third_instance(c_update);
// ....so on.
...
}
Hope helps!
Hold a function in the class.
#include <iostream>
#include <functional>
using namespace std;
class Foo
{
public:
Foo(const function<void ()>& f) : func(f)
{
}
void callFunc()
{
func();
}
private:
function<void ()> func;
};
void printFoo() { cout<<"foo"<<endl; }
void printBar() { cout<<"bar"<<endl; }
int main()
{
Foo a(printFoo);
Foo b(printBar);
a.callFunc();
b.callFunc();
}
You may have noticed that the end brace of a class is often followed by a semicolon, whereas the end braces of functions, while loops etc don't. There's a reason for this, which relates to a feature of struct in C. Because a class is almost identical to a struct, this feature exists for C++ classes too.
Basically, a struct in C may declare a named instance instead of (or as well as) a named "type" (scare quotes because a struct type in C isn't a valid type name in itself). A C++ class can therefore do the same thing, though AFAIK there may be severe limitations on what else that class can do.
I'm not in a position to check at the moment, and it's certainly not something I remember using, but that may mean you can declare a named class instance inheriting from a base class without giving it a class name. There will still be a derived type, but it will be anonymous.
If valid at all, it should look something like...
class : public baseclass // note - no derived class name
{
public:
virtual funcname ()
{
...
}
} instancename;
Personally, even if this is valid, I'd avoid using it for a number of reasons. For example, the lack of a class name means that it's not possible to define member functions separately. That means that the whole class declaration and definition must go where you want the instance declared - a lot of clutter to drop in the middle of a function, or even in a list of global variables.
With no class name, there's presumably no way to declare a constructor or destructor. And if you have non-default constructors from the base class, AFAIK there's no way to specify constructor parameters with this.
And as I said, I haven't checked this - that syntax may well be illegal as well as ugly.
Some more practical approaches to varying behaviour per-instance include...
Using dependency injection - e.g. providing a function pointer or class instance (or lambda) for some part of the behavior as a constructor parameter.
Using a template class - effectively compile-time dependency injection, with the dependency provided as a function parameter to the template.
I think it will be the best if you'll tell us why do you need to override a function for a specific instance.
But here's another approach: Strategy pattern.
Your class need a member that represent some behaviour. So you're creating some abstract class that will be an interface for different behaviours, then you'll implement different behaviours in subclasses of that abstract class. So you can choose those behaviours for any object at any time.
class A;//forward declaration
class Updater
{
public:
virtual ~Updater() {};//don't forget about virtual destructor, though it's not needed in this case of class containing only one function
virtual void update(A&) = 0;
}
class SomeUpdater
{
public:
virtual void update(A & a);//concrete realisation of an update() method
}
class A
{
private:
Updater mUpdater;
public:
explicit A(Updater updater);//constructor takes an updater, let's pretend we want to choose a behaviour once for a lifetime of an object - at creation
void update()
{
mUpdater.update(this);
}
}
You can use local classes, yet, personally, I consider the "hold function in the class" approach mentioned in the other answer better. I'd recommend the following approach only if doFunc must access internals of your base class, which is not possible from a function held in a member variable:
class ABase {
public:
void Func () { this->doFunc (); }
private:
virtual void doFunc () = 0;
public:
virtual ~ABase () { }
};
ABase* makeFirstA () {
class MyA : public ABase {
virtual void doFunc () { std::cout << "First A"; }
};
return new MyA;
}
ABase* makeSecondA () {
class MyA : public ABase {
virtual void doFunc () { std::cout << "Second A"; }
};
return new MyA;
}
int main () {
std::shared_ptr<ABase> first (makeFirstA ());
std::shared_ptr<ABase> second (makeSecondA ());
first->Func ();
second->Func ();
}
From a design patterns point of view, the "local classes" approach implements the template method pattern, while the "hold a function(al) in a member variable" approach reflects the strategy pattern. Which one is more appropriate depends on what you need to achieve.
I'm finding it difficult to describe this problem very concisely, so I've attached the code for a demonstration program.
The general idea is that we want a set of Derived classes that are forced to implement some abstract Foo() function from a Base class. Each of the derived Foo() calls must accept a different parameter as input, but all of the parameters should also be derived from a BaseInput class.
We see two possible solutions so far, neither we're very happy with:
Remove the Foo() function from the base class and reimplement it with the correct input types in each Derived class. This, however, removes the enforcement that it be implemented in the same manner in each derived class.
Do some kind of dynamic cast inside the receiving function to verify that the type received is correct. However, this does not prevent the programmer from making an error and passing the incorrect input data type. We would like the type to be passed to the Foo() function to be compile-time correct.
Is there some sort of pattern that could enforce this kind of behaviour? Is this whole idea breaking some sort of fundamental idea underlying OOP? We'd really like to hear your input on possible solutions outside of what we've come up with.
Thanks so much!
#include <iostream>
// these inputs will be sent to our Foo function below
class BaseInput {};
class Derived1Input : public BaseInput { public: int d1Custom; };
class Derived2Input : public BaseInput { public: float d2Custom; };
class Base
{
public:
virtual void Foo(BaseInput& i) = 0;
};
class Derived1 : public Base
{
public:
// we don't know what type the input is -- do we have to try to cast to what we want
// and see if it works?
virtual void Foo(BaseInput& i) { std::cout << "I don't want to cast this..." << std::endl; }
// prefer something like this, but then it's not overriding the Base implementation
//virtual void Foo(Derived1Input& i) { std::cout << "Derived1 did something with Derived1Input..." << std::endl; }
};
class Derived2 : public Base
{
public:
// we don't know what type the input is -- do we have to try to cast to what we want
// and see if it works?
virtual void Foo(BaseInput& i) { std::cout << "I don't want to cast this..." << std::endl; }
// prefer something like this, but then it's not overriding the Base implementation
//virtual void Foo(Derived2Input& i) { std::cout << "Derived2 did something with Derived2Input..." << std::endl; }
};
int main()
{
Derived1 d1; Derived1Input d1i;
Derived2 d2; Derived2Input d2i;
// set up some dummy data
d1i.d1Custom = 1;
d2i.d2Custom = 1.f;
d1.Foo(d2i); // this compiles, but is a mistake! how can we avoid this?
// Derived1::Foo() should only accept Derived1Input, but then
// we can't declare Foo() in the Base class.
return 0;
}
Since your Derived class is-a Base class, it should never tighten the base contract preconditions: if it has to behave like a Base, it should accept BaseInput allright. This is known as the Liskov Substitution Principle.
Although you can do runtime checking of your argument, you can never achieve a fully type-safe way of doing this: your compiler may be able to match the DerivedInput when it sees a Derived object (static type), but it can not know what subtype is going to be behind a Base object...
The requirements
DerivedX should take a DerivedXInput
DerivedX::Foo should be interface-equal to DerivedY::Foo
contradict: either the Foo methods are implemented in terms of the BaseInput, and thus have identical interfaces in all derived classes, or the DerivedXInput types differ, and they cannot have the same interface.
That's, in my opinion, the problem.
This problem occured to me, too, when writing tightly coupled classes that are handled in a type-unaware framework:
class Fruit {};
class FruitTree {
virtual Fruit* pick() = 0;
};
class FruitEater {
virtual void eat( Fruit* ) = 0;
};
class Banana : public Fruit {};
class BananaTree {
virtual Banana* pick() { return new Banana; }
};
class BananaEater : public FruitEater {
void eat( Fruit* f ){
assert( dynamic_cast<Banana*>(f)!=0 );
delete f;
}
};
And a framework:
struct FruitPipeLine {
FruitTree* tree;
FruitEater* eater;
void cycle(){
eater->eat( tree->pick() );
}
};
Now this proves a design that's too easily broken: there's no part in the design that aligns the trees with the eaters:
FruitPipeLine pipe = { new BananaTree, new LemonEater }; // compiles fine
pipe.cycle(); // crash, probably.
You may improve the cohesion of the design, and remove the need for virtual dispatching, by making it a template:
template<class F> class Tree {
F* pick(); // no implementation
};
template<class F> class Eater {
void eat( F* f ){ delete f; } // default implementation is possible
};
template<class F> PipeLine {
Tree<F> tree;
Eater<F> eater;
void cycle(){ eater.eat( tree.pick() ); }
};
The implementations are really template specializations:
template<> class Tree<Banana> {
Banana* pick(){ return new Banana; }
};
...
PipeLine<Banana> pipe; // can't be wrong
pipe.cycle(); // no typechecking needed.
You might be able to use a variation of the curiously recurring template pattern.
class Base {
public:
// Stuff that don't depend on the input type.
};
template <typename Input>
class Middle : public Base {
public:
virtual void Foo(Input &i) = 0;
};
class Derived1 : public Middle<Derived1Input> {
public:
virtual void Foo(Derived1Input &i) { ... }
};
class Derived2 : public Middle<Derived2Input> {
public:
virtual void Foo(Derived2Input &i) { ... }
};
This is untested, just a shot from the hip!
If you don't mind the dynamic cast, how about this:
Class BaseInput;
class Base
{
public:
void foo(BaseInput & x) { foo_dispatch(x); };
private:
virtual void foo_dispatch(BaseInput &) = 0;
};
template <typename TInput = BaseInput> // default value to enforce nothing
class FooDistpatch : public Base
{
virtual void foo_dispatch(BaseInput & x)
{
foo_impl(dynamic_cast<TInput &>(x));
}
virtual void foo_impl(TInput &) = 0;
};
class Derived1 : public FooDispatch<Der1Input>
{
virtual void foo_impl(Der1Input & x) { /* your implementation here */ }
};
That way, you've built the dynamic type checking into the intermediate class, and your clients only ever derive from FooDispatch<DerivedInput>.
What you are talking about are covariant argument types, and that is quite an uncommon feature in a language, as it breaks your contract: You promised to accept a base_input object because you inherit from base, but you want the compiler to reject all but a small subset of base_inputs...
It is much more common for programming languages to offer the opposite: contra-variant argument types, as the derived type will not only accept everything that it is bound to accept by the contract, but also other types.
At any rate, C++ does not offer contravariance in argument types either, only covariance in the return type.
C++ has a lot of dark areas, so it's hard to say any specific thing is undoable, but going from the dark areas I do know, without a cast, this cannot be done. The virtual function specified in the base class requires the argument type to remain the same in all the children.
I am sure a cast can be used in a non-painful way though, perhaps by giving the base class an Enum 'type' member that is uniquely set by the constructor of each possible child that might possibly inherit it. Foo() can then check that 'type' and determine which type it is before doing anything, and throwing an assertion if it is surprised by something unexpected. It isn't compile time, but it's the closest a compromise I can think of, while still having the benefits of requiring a Foo() be defined.
It's certainly restricted, but you can use/simulate coviarance in constructors parameters.