If I have two classes:
class A{
f();
}
class B{
f();
};
I need to assign one of these classes to an object based on a condition like:
define variable
if condition1
variable = A
else
variable = B
and then I would use the assigned variable.f();
You should look toward inheritance and virtual functions.
Code might look like
class Base
{
virtual void f() = 0;
};
class A : public Base
{
virtual void f()
{
//class A realization of f
}
};
class B : public Base
{
virtual void f()
{
//class B realization of f
}
};
And then you can do this
Base* VARIABLE = 0;
if (*condition*)
{
VARIABLE = new A();
}
else
{
VARIABLE = new B();
}
VARIABLE->f();
But it not always a good idea to use inheritance and virtual functions. Your classes A and B should have something in common, at least the meaning of function f().
Provided A and B are meant to be unrelated types (i.e. not part of an inheritance hierarchy), you could use Boost.Variant in combination with the boost::static_visitor<> class to achieve something similar:
#include <boost/variant.hpp>
#include <iostream>
struct A { void f() { std::cout << "A::f();" << std::endl; } };
struct B { void f() { std::cout << "B::f();" << std::endl; } };
struct f_caller : boost::static_visitor<void>
{
template<typename T>
void operator () (T& t)
{
t.f();
}
};
bool evaluate_condition()
{
// Just an example, some meaningful computation should go here...
return true;
}
int main()
{
boost::variant<A, B> v;
if (evaluate_condition())
{
A a;
v = a;
}
else
{
B b;
v = b;
}
f_caller fc;
v.apply_visitor(fc);
}
What you are doing is known in design patterns as the "Factory Pattern". The above answers cover how it should be implemented. You can get more information at How to implement the factory method pattern in C++ correctly and wiki (http://en.wikipedia.org/wiki/Factory_method_pattern).
Related
As we know in CRTP the derived class inherit base, as final inheritance.
What if we want make the derived class not-final but the 'overriding' functions is 'final'?
Is there any way to make it with static_assert?
Code sample:
template <typename D>
struct A
{
int f()
{
return static_cast<D*>(this)->g();
}
int g();
};
struct B : A<B> // usually final, but we want it inheritable
{
int g() // but this should be 'final'
{
// TODO: ???
return 1;
}
};
struct C : B
{
int g() // this is bad
{
return 2;
}
int h(); // this is permissive
};
#include <iostream>
template <typename D>
void f(A<D>& x)
{
std::cout << x.f() << std::endl;
}
int main()
{
B b;
C c;
f(b); // OK, it's 1
f(c); // BAD, it's 1
return 0;
}
You can use final for two purposes.
From https://en.cppreference.com/w/cpp/language/final
specifies that a virtual function cannot be overridden in a derived class or that a class cannot be inherited from.
You can use
struct B : A<B>
{
virtual int g() final
{
return 1;
}
};
to allow other classes to derive from B but not able to override g().
Another potential side benefit of using final is that an optimizing compiler might be able to resolve the function call at compile time instead of resolving at run time (Thanks #JesperJuhl).
I came up with a solution by using private tag in function signature:
template <typename D>
struct A
{
struct internal_tag
{};
int f()
{
return static_cast<D*>(this)->g({});
}
int g(internal_tag);
};
struct B : A<B>
{
int g(internal_tag)
{
return 1;
}
private:
using A<B>::internal_tag;
};
struct C : B
{
// int g(internal_tag) // int g(internal_tag) is prohibited
// {
// return 2;
// }
int h();
};
I am very new to c++ so I am trying to get a feeling of how to do things the right way in c++. I am having a class that uses one of two members. which one gets determined at instantiation. It looks something like
main() {
shared_pointer<A> a = make_shared<A>();
if ( checkSomething ) {
a->setB(make_shared<B>());
} else {
a->setC(make_shared<C>());
}
a->doStuff();
class A {
public:
doStuff() {
/*here I want to do something like call
m_b->doStuff() if this pointer is set and m_c->doStuff() if
that pointer is set.*/
}
setB( B* p ) { m_b = p; }
setC( C* p ) { m_c = p; }
B* m_b;
C* m_c;
}
}
B and C are some classes with doStuff() member function
There are many members like doStuff. Ideally I would avoid checking for nullptr in each of them. What is the best/most efficient/fastest way to create a switch between those two members?
Is there a way to use a static pointer so that I have a member
static **int m_switch;
and do something like
m_switch = condition ? &m_b : &m_c;
and call
*m_switch->doStuff();
Does the compiler here also replace the extra pointer hop because it is a static?
Is there any other smart way to do those switches?
Normally, class A would be an interface class, which both B and C would inherit and implement. But it sounds like you cannot do this for whatever reason.
Since you want to emulate this, you can start by making the interface:
class A_interface
{
public:
virtual void doStuff() = 0;
virtual void doThings() = 0;
virtual void doBeDoBeDo() = 0;
};
And then you make a template wrapper:
template< class T >
class A : public A_interface
{
public:
void doStuff() override { target.doStuff(); }
void doThings() override { target.doThings(); }
void doBeDoBeDo() override { target.doBeDoBeDo(); }
private:
T target;
};
This essentially does half of what your own example class A was trying to do, but now you can use a common interface. All you need to do is construct the correct templated version you want:
std::shared_ptr<A_interface> a;
if( checkSomething ) {
a = std::make_shared<A<B>>();
} else {
a = std::make_shared<A<C>>();
}
a->doStuff();
You need to have both members implement a common interface to use them similarly. But in order to do that, you need to define the interface and relay the calls to the B and C classes.
// existing classes
class B
{
public:
void doStuff() { std::cout << "B"; }
};
class C
{
public:
void doStuff() { std::cout << "C"; }
};
// define your interface
class I
{
public:
virtual void doStuff() = 0;
};
// new classes
class D : public B, public I
{
public:
void doStuff() override { B::doStuff(); }
};
class E : public C, public I
{
public:
void doStuff() override { C::doStuff(); }
};
// your A class
class A
{
public:
D* b = nullptr; // now type D
E* c = nullptr; // now type E
// your toggle
I* getActive()
{
if (b)
return b;
else
return c;
}
// simple doStuff() function
void doStuff()
{
getActive()->doStuff();
}
};
int main()
{
A a;
if (true)
a.b = new D; // need to initialize as D
else
a.c = new E; // need to initialize as E
a.doStuff(); // prints B
}
But typing this up made me realize that defining D and E could get really tiresome and against what you're trying to save. However, you can define a template to create them like #paddy has done.
There's no one-size-fits-all solution for your problem. What to use depends on your particular problem. A few possible answers:
Interfaces
Strategy Pattern
Pointers (to hold a function or class which implements doStuff)
An interface is like a contract. Any class which inherits from the interface must implement its members. For instance,
class IDoesStuff
{
public:
virtual ~IDoesStuff() {};
virtual void DoStuff() = 0;
};
Can now be used by other classes:
class Foo : public IDoesStuff
{
public:
virtual void DoStuff()
{
// ....
}
};
class Bar : public IDoesStuff
{
public:
virtual void DoStuff()
{
// ....
}
};
And now, in general, one may do:
Foo foo;
IDoesStuff *stuffDoer= &foo;
stuffDoer->doStuff();
This can be used in your particular use case as follows:
class A
{
IDoesStuff *stuffDoer; // Initialize this at some point.
public:
void doStuff() { stuffDoer->doStuff(); }
};
First you must change your memebr variables m_b and m_c to std::shared_ptr.
Add a member variable of type std::function(void()) to hold the target function you want to call. In your sample it is do_stuf.
In your setter functions you can bind target function to your std::function and in do_stuf just call std::function.
(You need a C++11 compiler)
class B
{
public:
void doStuff()
{
}
};
class C
{
public:
void doStuff()
{
}
};
class A
{
public:
void doStuff()
{
m_target_function();
}
void setB(std::shared_ptr<B> p)
{
m_b = p;
m_target_function = std::bind(&B::doStuff, m_b.get());
}
void setC(std::shared_ptr<C> p)
{
m_c = p;
m_target_function = std::bind(&C::doStuff, m_c.get());
}
std::shared_ptr<B> m_b;
std::shared_ptr<C> m_c;
std::function<void()> m_target_function;
};
int _tmain(int argc, _TCHAR* argv[])
{
std::shared_ptr<A> a = std::make_shared<A>();
bool use_B = false;
if (use_B)
{
a->setB(std::make_shared<B>());
}
else
{
a->setC(std::make_shared<C>());
}
a->doStuff();
}
In an example below I have a pretty typical CRTP example, two different derived classes that both have a method bar. The base class has a method foo which just forwards to some derived bar method
#include <iostream>
template<typename Derived>
class Base {
public:
void foo() {
static_cast<Derived*>(this)->bar();
}
};
class DerivedA : public Base<DerivedA> {
public:
void bar() {
::std::cout << "A\n";
}
};
class DerivedB : public Base<DerivedB> {
public:
void bar() {
::std::cout << "B\n";
}
};
int main() {
DerivedA a;
DerivedB b;
a.foo();
b.foo();
}
It doesn't seem like I can have an array / vector / etc. of the base class because it would have to have a type along the lines of Base<T> where T is different
Is there some kind of convention without virtual for being able to iterate over different derived classes assuming they all have the same method (bar in this case)?
You can use Boost.Variant. For example:
typedef boost::variant<DerivedA, DerivedB> Derived;
struct BarCaller : public boost::static_visitor<void> {
template <class T>
void operator()(T& obj) {
obj.bar();
}
};
int main() {
std::vector<Derived> vec{DerivedA(), DerivedB(), DerivedA()};
BarCaller bar;
for (Derived& obj : vec) {
obj.apply_visitor(bar);
}
}
This lets you store heterogeneous types in a vector or other STL container (by using a "discriminated union"), and lets you call a specific function on all of them regardless of their not having a common ancestor or any virtual methods.
It doesn't seem like I can have an array / vector / etc. of the base class because it would have to have a type along the lines of Base<T> where T is different.
You can have a base class of Base<T> for all T, then, you can have a list/vector/array of pointers to the base class, if that works for you.
struct BaseOne
{
virtual void foo() = 0;
virtual ~BaseOne() {}
};
template<typename Derived>
class Base : struct BaseOne {
public:
void foo() {
static_cast<Derived*>(this)->bar();
}
};
and then,
int main() {
std::vector<BaseOne*> v {new DerivedA, new DerivedB };
for ( auto item : v )
item->bar();
for ( auto item : v )
delete item;
}
Is there some kind of convention without virtual for being able to iterate over different derived classes assuming they all have the same method (bar in this case)?
No, there isn't.
As per now, variant has became part of the C++17 standard and the solution to the problem can be solved by std::variant and std::visit as follows.
The template class in the example is Interface<> and use the CRTP idiom to force derived class to implement helloImpl():
#include <iostream>
#include <vector>
#include <variant>
template<typename Implementer>
struct Interface {
void hello() const {
static_cast<Implementer const *>(this)->helloImpl();
}
};
A couple of class examples with different implementations of helloImpl()
struct Hello1 : public Interface<Hello1> {
void helloImpl() const {
std::cout << "Hello1" << std::endl;
}
};
struct Hello2 : public Interface<Hello2> {
void helloImpl() const {
std::cout << "Hello2" << std::endl;
}
};
And here is how to use it to store data in a vector<> container and its traversal:
int main() {
using var_t = std::variant<Hello1, Hello2>;
std::vector<var_t> items{Hello1(), Hello1(), Hello2()};
for(auto &item: items) {
std::visit([](auto &&arg) {
arg.hello();
}, item);
}
return 0;
}
Is it possible to pass this by default ?
Here is what I currently have
class A
{
public:
template<typename T>
void dowithT(T t) {}
};
class B
{
public:
A a;
B()
{
//Calling 'dowithT' with 'this'
a.dowithT(this);
}
};
This function requires passing this from the caller of the function every time. So I wondered if there is a way to encapsulate this task, so that you don't need to pass this to dowithT.
I tried to do something like this:
class A
{
public:
// '= this' doesn't compile
template<typename T>
void dowithT(T t = this) {}
};
class B
{
public:
A a;
B()
{
//Calling 'dowithT' without 'this'
a.dowithT();
}
};
Unfortunately, I can't use templates, so my first solution isn't an option.
Is this possible?
Edit: I gave a concrete answer with my own implementation below. Also with a few mor deatils of what I wanted in the end.
TL;DR No, this is not possible.
this is not the same type in every class, you can't generalize it, so no, not possible.
Additionally, what would this be if doWithT() was called from a non-member function? nullptr?
That's why it isn't possible. You have to use a template.
Instead of B having a member of type A, it can inherit from A, and use something like the "curiously recurring template pattern."
If you cannot make class A a template, you can still do it like so:
class A
{
protected:
template <class T>
void dowithT()
{
T* callerthis = static_cast<T*>(this);
// callerthis is the "this" pointer for the inheriting object
cout << "Foo";
}
};
class B : public A
{
public:
B()
{
dowithT<B>();
// Or A::dowithT<B>();
}
};
dowithT() must only be called by an inheriting class (hence I made it protected), with the template parameter the caller's own type, or you'll break everything.
You may achieve exactly what you want by using a private mixin class to provide the dowithT method that takes no arguments:
#include <iostream>
#include <typeinfo>
class A
{
public:
template<typename T>
void dowithT(T* t) {
std::cout << "Hello, World" << typeid(*t).name() << std::endl;
}
};
template<class Owner>
struct calls_a
{
void dowithT()
{
auto p = static_cast<Owner*>(this);
p->a.dowithT(p);
}
};
class B
: private calls_a<B>
{
friend calls_a<B>;
A a;
public:
B()
{
//Calling 'dowithT' with 'this'
dowithT();
}
};
int main()
{
B b;
}
No, it is not possible. There is nothing really special about this when used as an argument to a function taking T* (template or not), it's just a pointer like any other.
this A is different from this B. In your first code, this refers to the caller, while in the second this refers to the callee. Thus what you want to do isnt really possible.
Here's one possibility, which might, or might not suit your needs:
template<typename T>
class A
{
public:
A(T t) : t(t) {}
void dowithT()
{
cout << "Foo";
}
private:
T t;
};
class B
{
public:
A<B*> a;
B() : a(this)
{
a.dowithT();
}
};
You could use a private method in class B that acts as a relay, and use the constant nullptr as a special value for this, if you want to be able to pass other values:
class B
{
public:
A a;
B()
{
//Calling 'dowithT' with 'this'
innerdo();
}
private:
void innerdo(B *p = nullptr) {
if (p == nullptr) p = this;
a.dowithT(p);
}
};
If you only need to pass this it is even simpler
void innerdo() {
a.dowithT(this);
}
After trying out various things you mentioned, I'd like to give my answer/solution to the problem myself to clarify some details:
#include <iostream>
using namespace std;
#include <functional>
template <typename CallerType>
class AFunctionConstructor{
private:
virtual void abstr()
{}
public:
typedef void(CallerType::*CallerTypeFunc)();
function<void()>* constructFunction(CallerTypeFunc func)
{
CallerType* newMe = dynamic_cast<CallerType*> (this);
return new function<void()>(std::bind(func,newMe));
}
};
class A : public function<void()>
{
protected:
public:
A();
A(function<void()>* func) : function<void()>(*func)
{}
};
// now create ressource classes
// they provide functions to be called via an object of class A
class B : public AFunctionConstructor<B>
{
void foo()
{
cout << "Foo";
}
public:
A a;
B() : a(constructFunction(&B::foo)) {}
};
class C : public AFunctionConstructor < C >
{
void bar()
{
cout << "Bar";
}
public:
A a;
C() : a(constructFunction(&C::bar)) {}
};
int main()
{
B b;
C c;
b.a();
c.a();
cout << endl;
A* array[5];
array[0] = &b.a; //different functions with their ressources
array[1] = &c.a;
array[2] = &b.a;
array[3] = &c.a;
array[4] = &c.a;
for (int i = 0; i < 5; i++) //this usability i wanted to provide
{
(*(array[i]))();
}
getchar();
return 0;
}
Output :
FooBar
FooBarFooBarBar
This is as far as i can press it down concerning examples. But i guess this is unsafe code. I stumbled across possible other and simpler ways to achieve this (other uses of std::function and lambdas(which i might have tried to reinvent here partially it seems)).
At first I had tried to pass "this" to the bind function in function<void()>*AFunctionConstructor::constructFunction(CallerTypeFunc func)
,though, which i now get through the dynamic upcast.
Additionally the functionality of AFunctionConstructor was first supposed to be implemented in a Constructor of A.
Or simply put
can I do some thing like
class A {
public:
virtual void foo() = 0;
};
class B {
public:
A *a;
b(){
a = new A() { void foo() {printf("hello");}
}
};
No, C++ doesn't have anonymous classes like Java's.
You can define local classes, like this:
class B {
public:
A *a;
b(){
struct my_little_class : public A {
void foo() {printf("hello");}
};
a = new my_little_class();
}
};
Or maybe just a nested class:
class B {
private:
struct my_little_class : public A {
void foo() {printf("hello");}
};
public:
A *a;
b(){
a = new my_little_class();
}
};
In C++03, local classes have some limitations (for example, they can't be used as template parameters) that were lifted in C++11.
In Java, anonymous classes are sometimes used to do what other languages do with anonymous functions like, for example, when you create an anonymous implementation of Runnable. C++11 has anonymous functions (also known as lambdas), so that could be an option if this is what you're trying to achieve.
Same answer as for the others, but if you wish to emulate such behavior you can (I don't recommend it though) :
struct Interface
{
virtual void doStuff() const = 0;
virtual ~Interface() {}
};
#define newAnon(tmp_name, parents, body, args...) \
({ \
class tmp_name : \
parents \
{ \
body; \
}; \
new tmp_name(##args); \
})
Interface *getDefault()
{
return newAnon(__tmp__, public Interface,
public:
virtual void doStuff() const {
std::cout << "Some would say i'm the reverse" << std::endl;
});
}
Beware though because you cannot have a static member in this new class, and that this is taking advantage of the Gcc/G++ statement expression : Statement-Exprs
A solution for static member would be the following, imagine we want a static int i that increments itself in a few situations in our previous class tmp, this would look like this :
struct Interface
{
virtual void doStuff() const = 0;
virtual void undoStuff() const = 0;
virtual ~Interface() {}
};
newAnon(__tmp__, Interface,
static int &i() {
static int i(0);
return i;
}
public:
virtual void doStuff() const {
std::cout << "call n°" << i()++ << std::endl;
}
virtual void undoStuff() const {
std::cout << "uncall n°" << i()-- << std::endl;
});
The result is that all new pointers given by getDefault() will refer to the same integer.
Note that using c++11's auto you can access all the public members as expected and use hierarchy to create a child of said type :
auto tmp = newAnon(...);
struct Try : decltype(*tmp+) {
Try() { std::cout << "Lol" << std::endl; }
};
Try a; // => will print "Lol"
Update:
A more modern c++ (14-17) without extensions would be
#define newAnon(code...) \
[&](auto&&... args) {\
struct __this__ : code;\
return std::make_unique<__this__>(std::forward<decltype(args)>(args)...); \
}
auto ptr = new_anon(interface { ... })(arguments);
No.
But this idiom is frequent in Java when passing callbacks to an API. If this is what you want (register callbacks for an API), you may want to use signals, like implemented on Boost.Signals or libsigc++ (the best way to go in this case).
Also, closer in syntax to what you want, new C++ specification (C++11, supported by most recent compilers) also allows for lambda functions:
template<class F>
void func(F callable) {
callable(); // Callable is an object that can be called as a function.
}
void a() {
method([]() {
printf("hello");
}); // This anonymous function was defined here...
}
If you really want to define a new class "on the fly", it cannot be done inline, but can be done "just above":
class A {
public:
virtual void foo() = 0;
};
class B {
public:
A *a;
void b(){
class MyImplementation: public A {
public: void foo() { printf("hello"); }
};
a = new MyImplementation();
}
};
The class can even be anonymous, but you can only create the object on stack (i.e. you can't use new on an anonymous class, and it will be deallocated upon function return):
void function_that_uses_but_does_not_stores_A(A* obj);
void function(){
class : public A {
public: void foo() { printf("hello"); }
} obj;
function_that_uses_but_does_not_stores_A(&obj);
};
No. Everything in C++ has to be defined before it can be used. In your case, since you want to override A::foo(), you have to derive a new class, and then B can instantiate that class, eg:
class A
{
public:
virtual void foo() = 0;
};
class A1 : public A
{
public:
void foo() { printf("hello"); }
};
class B
{
public:
A *a;
B()
{
a = new A1();
}
};