How to save an object inside another object in C++ - c++

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.

Related

C++ two dependent objects?

class D {
public:
void HelloWorld(){cout << "Hello" << endl;}
};
class B {
public:
void SetCallBack(std::function<void()> callback) {
callback_ = callback;
}
private:
std::function<void()> callback_;
};
class A {
public:
A(B *b) : b_(b) {}
std::function<void()> Helper(){
return [](){d_->HelloWorld(); };
}
private:
B *b_;
std::unique_ptr<D> d_;
};
class C {
public:
C(std::unique_ptr<B> b, std::unique_ptr<A> a)
: b_(std::move(b)),
a_(std::move(a)) {
b_->SetCallBack(a_->Helper());
}
private:
std::unique_ptr<B> b_;
std::unique_ptr<A> a_;
};
Questions:
When B holds a copy of A's member function, does it mean B also holds a pointer to A?
Given A's constructor depends on B, B has to be declared first in C and destructed later. But is this a buggy code that A also depends on B and when A is destructed if B calls the callback, what happens?

When I get a case of `slicing`?

Let's look the next code (for example):
class A {
int n;
public:
int f() const { return n; }
void set(int i) { n = i; }
};
class B : public A {
public:
int g() const { return f()+1; }
};
void h(const A& a) {
a.f();
}
int main() {
B b;
A& a = b;
A* ptrA = new B;
h(b);
delete ptrA;
return 0;
}
Now, Let's look about these lines code:
A& a = b; // Is there "slicing"? (why?)
A* ptrA = new B; // Is there "slicing"? (why?)
A a = b; // Is there "slicing"? (why?)
I do not really understand when I want to use any of them, and when, alternatively, you will not be allowed to use one of them. What is really the difference between these lines..
Slicing is when you assign a derived object to a base instance. For example:
B b;
A a = b;
The issue here is that the copy constructor for A that is being called only sees the A part of B, and so will only copy that. This is an issue if your derived class has added additional data or overridden the behaviour of A.
When you assign an object to a reference or a pointer there is no slicing. So
A &a = b;
Is fine, as is:
A *a = &b;

Pointer to a class method in c++ [duplicate]

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.

Passing member function (or workaround)

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.

is this possible in C++?

to create an instance of another class from a class even if the class I want to have an instance of is declared next of the class I am creating an instance from. Just like in C# and Java.
Thank you
You can use a forward declaration for some purposes, but you will need to have the complete type whenever you actually make use of it. It could be advisable to make the question more specific as to what you really want to achieve, as there might be simpler approaches to your problem (if order is important it might indicate a circular dependency between classes A and B, and that is not usually good).
class B;
class A
{
public:
A( B b, B* bp, B& br ) : bp_(bp), br_(br) {} // ok, incomplete types can be used as argument types
B f()
// { return B(); } // nok: cannot create objects of incomplete type
;
B* f2() { return bp_; } // ok
B& f3() { return br_; }; // ok
void g()
// { bp_->g(); br_.g(); } // nok: cannot call methods of an incomplete type
;
void g( B const & b )
// { b.g(); } // nok: cannot call methods of an incomplete type
private:
B * bp_; // ok (also const version)
B & br_; // ok (also const version)
// B b_; // nok: B must be a complete type here
};
class B { // A is complete, any use is correct here
void g() {}
};
// From here on, B is a complete type and can be used in any possible way
B A::f() {
return B(); // ok, now B is complete
}
void A::g() {
br_.g(); // ok, B is complete here
bp_->g(); // ok, B is complete here
}
void A::g( B const & b ) {
b.g();
}
Sure. You just need a forward declaration. Something like this works just fine:
#include <iostream>
class B;
class A {
public:
void hello( B &b );
void meow();
};
class B {
public:
void hello( A &a );
void woof();
};
void A::hello( B &b ) { b.woof(); }
void A::meow() { std::cout << "Meow!" << std::endl; }
void B::hello( A &a ) { a.meow(); }
void B::woof() { std::cout << "Woof!" << std::endl; }
int main() { A a; B b; a.hello( b ); b.hello( a ); return 0; }
The key here is that you can only use pointers or references to a class until it has been fully defined. So in the example I gave, the hello() method in A can be declared to take a reference to B, even though we haven't defined B at the point. After the definition of B, however, the definition of the method A::hello() is free to use B as it pleases.
I guess you mean to do something like this:
class B; //Forward declaration
class A
{
private:
B b;
};
class B
{
};
This is not possible in C++ as the compiler needs to know the sizeof(B) when compiling class A.
As a solution what you can do is:
class B; //Forward declaration
class A
{
public:
A();
~A();
private:
B* m_pB; //Store a pointer to B
};
class B
{
};
A::A()
{
m_pB = new B; //Create an instance of B
}
A::~A()
{
delete m_pB; //Explictly deallocate the memory.
m_pB = NULL;
}
Once you forward declare B in the header you can use it in the .cpp file without trouble to access public variables and methods.