I want to do the following:
class A{
private:
//some data
B b;
double f(double);
public:
A(){
b = new B(f); // does not work of course
}
};
class B{
public:
B(double (*func)(double));
};
Class B is supposed to solve a mathematical problem specified by the function func. Class A should now use B to solve this problem for func=f. The member function f accesses the private data members of A.
The problem is, of course that I cannot simply pass a pointer to member function. I know there are ways to do that, but B should still be able to take any function, not only members of A.
Until now, I just made f and the members of A static, but I think this is a rather bad design. Can you think of any workaround for this?
You can use the standard std::function<> template as a polymorphic wrapper for your functions.
Your class B simply store an instance of std::function<double (double)> and call it through foo :
class B
{
public:
B(const std::function<double (double)>& func) : func(func) {}
void foo(double d)
{
std::cout << func(d);
}
private:
std::function<double (double)> func;
};
While your class A build its B member with one of its member function (f), thanks to std::bind :
class A
{
public:
double md;
B b;
double f(double d) const
{
return md * d;
}
public:
A(double d) : md(d), b(std::bind(&A::f, this, std::placeholders::_1)) { }
};
We can now simply use it :
int main() {
A a(42);
a.b.foo(2); // Output : 84
}
Live demo here.
How about using polymorphism as an alternative to your current design?
For example:
class A
{
protected:
virtual double f(double x) = 0;
};
class B1 : public A
{
public:
double f(double x) {return x+1.0;}
};
class B2 : public A
{
public:
double f(double x) {return x+2.0;}
};
...
A* arr[4];
arr[0] = new B1;
arr[1] = new B2;
arr[2] = new B1;
arr[3] = new B2;
for (int i=0; i<4; i++)
cout << arr[i]->f(0.0);
This a fully working program for your sample.
#include <memory>
#include <iostream>
#include <functional>
class B
{
public:
B(std::function<double(double)> func)
{
std::cout<<func(1.0);
}
};
class A
{
private:
std::unique_ptr<B> b;
double f(double)
{
std::cout<<"A::f";
return 2.0;
}
public:
A() : b(new B(std::bind(&A::f, this, std::placeholders::_1)))
{
}
};
int main()
{
A a;
}
Please note you don't destroy b there and also keep in mind you are passing this to B, thing that might be dangerous (B might be alive after A is destroyed and if you use this inside f... boom!).
I would also suggest avoiding pointers and if this is not possible using std::unique_ptr
EDIT: And a version without b as pointer, std::function and std::bind
#include <iostream>
class A;
class B
{
public:
B(A* obj, double(A::*func)(double))
{
std::cout<<(obj->*func)(1.0);
}
};
class A
{
private:
B b;
double f(double)
{
std::cout<<"A::f";
return 2.0;
}
public:
A():b(this, &A::f)
{
}
};
int main()
{
A a;
}
Since function f() is not static it's type is "double ( A::* )(double)", not "double (*)(double)".
However for this particular case it is better re-design.
Does really A consist of data and instance of problem solver (class B), or A consist of data and delegates some operations to B?
Does really class B need some to know about methods from class A, or it expects data in some format?
class DataType {};
class ResultType {};
class A
{
DataType data;
DataType preprocess(Data d) {/*...*/}
ResultType process() { return B::compute(data); }
bool isSolvable() { return B::solve(preprocess(data)); }
};
class B
{
public:
ResultType compute(DataType);
bool solve(DataType);
};
Possible solution:
class A
{
B* b;
static double f(double d); //static change function type form `double(A::*)(double)` to `double(*)(double)`
public:
A()
{
b = new B(f);
}
}
only drawback that f cant take any data form A or B.
Related
I have 2 classes lets say Class A and Class B,
class A {
public:
A(B b);
B GetB();
private:
B b;
};
class B {
public:
B();
void IncrementCounter();
int GetCounter();
private:
int counter = 0;
};
I want to pass an object of type B to class A's constructor and then save this instance of class B in Class A instance.
What is the best way to pass class B instance as a parameter, and what is the best way to save class B instance in class A instance.
Note: I do not want to create copies of class B instance, I want A.getB().GetCounter to always be the same as b.GetCounter().
int main(){
B b;
A a(b);
b.IncrementCounter();
a.getB().IncrementCounter();
// then b.GetCounter() is same as a.getB().GetCounter() and both = 2
}
I see people using pointers/smart pointer and references/std:reference_wrapper, what is the difference?
Use std::shared_ptr if you don't want copies, example :
I assume you are familiar with references, const references and const member functions.
#include <memory>
#include <iostream>
class B
{
public:
B()
{
number_of_instances++; // keep track of number of instances of class B
}
void IncrementCounter()
{
counter++;
}
int GetCounter() const
{
return counter;
}
int NumberOfInstances() const
{
return number_of_instances;
}
private:
int counter{ 0 };
static int number_of_instances;
};
class A
{
public:
A(const std::shared_ptr<B>& b) :
m_b{ b }
{
}
// return a reference to the object shared_ptr m_b points to
B& GetB()
{
return *m_b;
}
// return a const reference to the object shared_ptr m_b points to
const B& GetB() const
{
return *m_b;
}
private:
// https://en.cppreference.com/w/cpp/memory/shared_ptr
std::shared_ptr<B> m_b;
};
int B::number_of_instances{ 0 };
int main()
{
auto b = std::make_shared<B>();
b->IncrementCounter();
A a1(b);
A a2(b);
std::cout << "number of instances of B = " <<b->NumberOfInstances() << "\n";
std::cout << "shared_ptr<B> reference count = " << b.use_count() << "\n";
std::cout << a1.GetB().GetCounter();
return 0;
}
Note: I do not want to create copies of class B instance, I want A.getB().GetCounter() to always be the same as b.GetCounter().
Then you need to make A store a B& reference instead of a B object instance, eg:
class A {
public:
A(B& b);
B& GetB();
private:
B& b;
};
A::A(B& b) : b(b) {
}
B& A::GetB() {
return b;
}
As long as the B object outlives the A object (which it does in your example), you will be fine, no (shared) pointers will be needed.
However, since you are declaring A before B, you can't use B at all in A as you have shown. The compiler won't know what B is while parsing A.
Since B doesn't depend on A for anything, you can simply swap the order of their declarations, eg:
class B {
public:
B();
void IncrementCounter();
int GetCounter();
private:
int counter = 0;
};
class A {
public:
A(B& b);
B& GetB();
private:
B& b;
};
Otherwise, if that is not an option for your situation, then you will have to use a forward declaration of B before declaring A, eg:
class B; // <--
class A {
public:
A(B& b);
B& GetB();
private:
B& b;
};
class B {
public:
B();
void IncrementCounter();
int GetCounter();
private:
int counter = 0;
};
Forward declaration only work when dealing with references and pointers, not with instances.
I have an abstract class A with the pure virtual method void foo(int a) = 0
Then I have several classes that inherit from A and all of them define the method foo. But I need one of them, B, to make it so foo takes an extra parameter, int b, so sort of an overload.
Then I would like to do this:
A *bInstance = new B();
bInstance -> foo(1, 2);
But I get an error telling me that foo is taking too many parameters.
Writing this, I realize it's kind of a weird thing to do so maybe you can't do this and it's good that you can't do it. But in case it is possible, please do tell me how I should go about it.
You can use the overloaded function of B only if the pointer to use is of type B.
See:
#include <iostream>
#include <memory>
class A{
public:
virtual void foo(int a) = 0;
};
class B : public A
{
public:
virtual void foo(int a) override
{
}
void foo(int a, int b)
{
std::cout << a << "," << b;
}
};
int main(){
auto b = std::make_shared<B>();
b->foo(1, 2);
//to use a:
A* aPtr = b.get();
aPtr->foo(1);
return 0;
}
Although Bernd's answer is a possiblility, you must ask yourself what the effect of an overload is. E.g., think of the following.
std::unique_ptr<A> bAsA = std::make_unique<B>();
bAsA->foo(1, 2); // no worky.
bAsA->foo(1); // works, but what should it do?
It there's a different interface between A and B, I would suggest to add a layer of abstraction in form of a new base class (which I will call C).
So instead of
struct A {
// common
virtual void bar() {}
// class specific
virtual void foo(int) = 0;
};
struct B: public A {
// weird unused override which is still available
void foo(int) override {}
// class specific
void foo(int, int) {}
};
use
struct C {
// common
virtual void bar() {}
};
struct A: public C {
// class specific
virtual void foo(int) = 0;
};
struct B: public C {
// class specific
void foo(int, int) {}
};
You can fully achieve want you want using a default parameter:
class A
{
public:
virtual void foo(int a, int b = 0) = 0;
virtual ~A() = default;
};
class B : public A
{
public:
void foo(int a, int b) override { }
};
class C : public A
{
public:
void foo(int a, int b = 0) override { }
};
int main()
{
A* b = new B();
A* c = new C();
b->foo(1, 2);
c->foo(1);
}
You don't have to use this parameter in C::foo implementation (and any other derived classes) if you don't need to.
This question already has answers here:
C++ Call Pointer To Member Function
(4 answers)
Closed 5 years ago.
A have a lot of B classes, a class A has one object b. This object b has a function (calc) that needs a pointer to a method in an object of A. This method (fun) acess private variables in class (in my example just return 3).
class A;
class B {
public:
virtual int calc ( int (A::*fun)()) { return 2*fun(); };
};
class A {
B* b;
public:
A (B* b_) : b (b_) {};
int fun() { return 3; };
int run(){ return b->calc(&A::fun); };
};
int main() {
B* b = new B();
A a(b);
a.run();
return 0;
}
How can I use a pointer to a method correctly in definition of calc method in class B?
I am getting this error message:
teste.cpp:10:58: error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘fun (...)’, e.g. ‘(... ->* fun) (...)’
virtual int calc ( int (A::*fun)()) { return 2*fun(); };
^
I recommend the std::function approach if it's feasible for you. However, for the sake of completeness, here's how you would correctly use pointer-to-member functions.
The pointer-to-member itself doesn't store the "current" instance of A, so you need to pass that explicitly. Then you use the special ->* (or .*) syntax to call it.
virtual int calc (A* value, int (A::*fun)()) {
return 2 * (value->*fun)();
};
Then you would call it as b->calc(this, &A::fun);.
You can do it your way, but the member function must be called on a particular instance:
class A;
class B {
public:
virtual int calc(A* a, int (A::*fun)()) { return 2 * (a->*fun)(); };
};
class A {
B* b;
public:
A(B* b_) : b(b_) {};
int fun() { return 3; };
int run() { return b->calc(this, &A::fun); }; // now also passing this pointer
};
int main() {
B* b = new B();
A a(b);
a.run();
return 0;
}
If you can live without calc() being virtual then a lambda is also an option:
class A;
class B {
public:
template<typename T>
int calc(T fun) { return 2 * fun(); };
};
class A {
B* b;
public:
A(B* b_) : b(b_) {};
int fun() { return 3; };
int run() {
return b->calc([this]() {return fun(); } );
};
};
int main() {
B* b = new B();
A a(b);
a.run();
return 0;
}
A pointer-to-class method is defined and initialized as (assuming SomeFn matches the signature):
RetType (ClassName::*pfn)(Args) = &ClassName::SomeFn;
And is called as:
ClassName * ptr = GetClassPtr();
(ptr->*pfn)(arg, arg);
If you are able to use C++11, then you should use std::function and std::bind: Otherwise you need to use a pointer to member function + a pointer to the instance.
With C++11
#include <functional>
class B {
public:
virtual int calc (std::function<int()>&& fun) { return 2 * fun(); }; };
};
class A {
B* b;
public:
A (B* b_) : b (b_) {};
int fun() { return 3; };
int run() { return b->calc(std::bind(&A::fun, this)); };
};
Without C++11
class B {
public:
virtual int calc (int(A::*fnptr)(), A* a) { return 2 * (a->*fnptr)(); };
};
class A {
B* b;
public:
A (B* b_) : b (b_) {};
int fun() { return 3; };
int run() { return b->calc(&A::fun, this); };
};
See example here.
I'm fairly new to object-oriented program, so maybe this is a basic question, but I'd appreciate any help you can offer.
If I have a class B, which is derived from class A, is there some way for objects of class B to access class B's member functions from within member functions of class A? So in the example below I might have a call to function2 from within function1 if the object initially calling function1 is of type B. Is this possible, and if so, how do I accomplish it? Thanks!
class A
{
public:
int a;
int b;
A(){}
A(int a, int b) { this->a = a; this->b = b; }
int function1();// { call function2 if class B }
};
class B : public A
{
public:
int c;
int d;
B(){}
B(int c, int d) { this->c = c; this->d = d; }
int function2();
};
A function inside A doesn't have any idea of the fact that a class B which extends A exists and which methods it has.
To be able to invoke a specific method implemented in B from A you need to declare it in A as virtual, possibly pure virtual (= 0).
class A {
protected:
virtual void function2() = 0;
public:
void function1() { this->function2(); }
}
class B : public A {
protected:
void function2() override { ... }
}
A virtual method is resolved at runtime, this means that when invoked, the more specific implementation for the object on which it is called is executed. A pure virtual method doesn't have any base implementation, this makes A abstract and forbids its instantiation.
EDIT: a final note, don't call virtual methods from base constructors or destructors. It is dangerous and a bad practice, not that this is your case but you never know.
Yes. You need to define function2() as a virtual function in class A. Then calling it from function1 will result in B's function2() being called if the object is actually a B. For example:
class A
{
public:
int a;
int b;
A(){}
A(int a, int b) { this->a = a; this->b = b; }
int function1() { return this->function2(); }
virtual int function2() { return 0; }
};
class B : public A
{
public:
int c;
int d;
B(){}
B(int c, int d) { this->c = c; this->d = d; }
int function2() override { return 999; }
};
If there is no sensible implementation of function2 for A, then it would never make sense to have an A object. You can express this by declaring function2 to be pure virtual; e.g.
virtual int function2() = 0;
virtual allows you to override function in parent class.
class A
{
public:
A(){}
A(int a, int b):a(a), b(b) {}
int function1() { return this->function2(); }
virtual int function2() { //what function2 in parent class should do }
private:
int a;
int b;
};
class B : public A
{
public:
B(){}
B(int c, int d):c(c), d(d) {}
int function2() { //what function2 in child class should do }
private:
int c;
int d;
};
I've always worked with pointers and avoided references because I didn't understand how to work with them very well. Today I was working on a small project and decided to use references instead and ran into some behavior I'm not sure how to work around. Basically I have a factory (Factory) that creates either an object of type B or C, both of which are derived from A.
class Factory
{
public:
void create(A& container, int a) //This is for creating an object of B
{
B result;
result.Func(a);
container = result;
}
void create(A& container, int a, int b) //This is for creating an object of C
{
C result;
result.Func(a, b);
container = result;
}
}
class A
{
public:
virtual void Func(int a) //This is used for an object of B
{
var1 = a;
};
virtual void Func(int, int) {}; // This is used for an object of C
private:
int var1;
}
class B : public A
{
//Relies of base class Func to set the variable var1;
}
class C : public A
{
public:
void Func(int a, int b)
{
A::Func(int a)
var2 = a1;
}
private:
int var2;
}
The issue arises when I try to do the following
Factory factory;
A a;
factory.create(a, 1); //Works fine because B and A have only 1 variable
factory.create(a, 1, 1); //a only contains A part of C
When I check the debugger, there is no sign of var2 to in a after the 2nd create call. I understand its because I'm using a reference to the base type of C and only the A part of C gets stored in the container, but is there a workaround? I know I can just switch A to A*, but I'm interested if there is a non-pointer based solution.
TL;DR
Is there a way to store an object of a derived class in a reference of the base class without using pointers?
I feel compelled to point out that a reference of type T is logically equivalent to a T * const. So technically, you can't get around using pointers.
To answer your question, it is absolutely possible to store a derived class in a reference to a base class. The issue is that A, B, and C all have potentially difference sizes. Here is one solution:
#include <stdio.h>
class A
{
public:
virtual void Function()
{
printf("A\n");
}
};
class B : public A
{
public:
virtual void Function()
{
printf("B: %d\n", var1);
}
int var1;
};
class C : public A
{
public:
virtual void Function()
{
printf("C: %d, %d\n", var1, var2);
}
int var1, var2;
};
class Factory
{
public:
A & Create(int a)
{
B &b = *new B;
b.var1 = a;
return b;
}
A & Create(int a, int b)
{
C &c = *new C;
c.var1 = a;
c.var2 = b;
return c;
}
};
Called like:
Factory factory;
A &a1 = factory.Create(0);
A &a2 = factory.Create(1, 2);
a1.Function();
a2.Function();
Which will print:
B: 0
C: 1, 2
Unfortunately, it's not possible to allocate an A and then assign a B or C to it later, since their sizes don't match. You either must use a reference/pointer with dynamic allocation, or know the type ahead of time.