Lets say that you have two classes defined as such:
class A {
double a;
A(double d)
{
a = d;
}
};
class B {
double b;
B(A a)
{
b = exp(a.a);
}
};
Then lets say that you wish to have a main that does the following:
A a(3.14);
B b(a);
print(b.b) // 23.1......
a.a = 2.71
print(b.b) // 15.1......
I am not sure what to call this other than something like dynamic evaluation or something. If this is possible using C++, what is it called?
I am sorry for the vagueness in this question, but I have no idea how to describe it any better.
It seems that you want to store reference of A in B. Working example:
#include <iostream>
#include <cmath>
struct A
{
double value;
};
class B
{
A& a_;
public:
B(A& a) :a_(a) { }
double value() {return std::exp(a_.value);}
};
int main()
{
A a{3.14};
B b(a);
std::cout << b.value() << '\n'; // 23.1039
a.value = 2.71;
std::cout << b.value() << '\n'; // 15.0293
}
What you're asking about is called "reactive programming", and in paticular reactive properties. Reactive programming is not built into C++, but there are various libraries out there to support the reactive paradigm.
I am only a begginer, but this is how I would approach it.
Let me assume that you want strictly what is written inside your main, and that your print does nothing else but printing.
With these assumption, print(b.b) has no way to know that a.a has been modified. In C++ the accessing to a member object cannot be overloaded. Therefore, we cannot add the functionality of checking the current value of a.a.
The only places that I see in which you could introduce that check are in print(...) or in a.a = 2.71.
We can add this functionality in operator=(const double&) of the member a of the instance a of A. For this, this object needs to know which instance b, or instances, of B to 'tell' that it was updated. The member a of A should be a type that behaves like a double but we will provide our own operator=(...).
For example
A.h can be
#pragma once
class B;
class UpdatableDouble {
public:
double d;
B* myb; // We will tell, in this example, only one B that it needs to update.
UpdatableDouble(const double& d) : d(d), myb(nullptr) {};
operator double() {
return d;
};
const double& operator=(const double& d);
// Add, as needed, the rest of the behavior of double.
};
class A {
public:
UpdatableDouble a;
A(const double &d) : a(d) {};
};
B.h can be
#pragma once
#include <cmath>
class A;
class B {
public:
double b;
B(A& a) : b(exp(a.a)) {
a.a.myb = this;
}
void update(const double& d) {
b = exp(d);
}
};
and then in the Main.cpp
#include <iostream>
#include <string>
#include "A.h"
#include "B.h"
const double& UpdatableDouble::operator=(const double& otherd) {
d = otherd;
myb->update(d);
return d;
};
void print(double& d) {
std::cout << d << std::endl;
};
int main() {
A a(3.14);
B b(a);
print(b.b); // 23.1......
a.a = 2.71;
print(b.b); // 15.1......
std::string wait;
std::cin >> wait;
return 0;
}
No, what you're asking based on your refining comments is not possible. There is no way to update the value b.b when a.a changes, without recalculating std::exp(a.a). Thus you need a function call to do that, and pretty much the best way you can do that is how #ÖöTiib has shown in his answer.
Related
I have a code similar to the minimal example below, where the function g is provided by a library and expects double (*)(double) as an argument. I cannot change this. The example code does not compile because the member has signature double (*C::)(double) as explained in e.g. this post, with a number of possible solutions.
#include <iostream>
double g(double (*f)(double x)) { return f(0); };
class C
{
public:
C(double b) { a = b; };
double f2() { return g(&f1); };
private:
double a;
double f1(double x) { return x + a; };
};
int main()
{
C c (1);
std::cout << c.f2() << std::endl;
return 0;
}
I wonder what the best way to implement this is given that I don't want to point to C::f1 outside the class but within another member function. As far as I understand, the member function C::f1 is not static since it is only fully known after an instance of the class is initialised. Since speed is also a concern: would this be a problem with any of the possible solutions proposed elsewhere for similar versions of this issue?
Make your f1 function static:
static double f1(double x) { return x + a; };
This gives it the same signature as what your g function expects. Since a static function does not have a hidden this pointer, you will have to find some other way to get the value of a into it.
Okay, based on the comments and ideas from the post mentioned before, I will suggest to change g as follows and add a wrapper function f2_wrapper.
#include <iostream>
double g(double (*f)(double x, void *context), void *context)
{
return f(0, context);
};
class C
{
public:
C(double b) { a = b; };
double f1(double x) { return x + a; };
double f2();
private:
double a;
};
double f2_wrapper(double x, void* context)
{
C *c = (C*) context;
return c->f1(x);
}
double C::f2() { return g(&f2_wrapper, this); }
int main()
{
C c (1);
std::cout << c.f2() << std::endl;
return 0;
}
I want to write an object-oriented wrapper around old C-style functions, while keeping the actual function names the same. Take a look at an example:
#include <iostream>
void doStuff(int a, float b)
{
std::cout << "a = " << a << ", b = " << b << "\n";
}
class Stuff
{
private:
int a;
float b;
public:
Stuff(int newA, float newB) : a(newA), b(newB) { }
int getA() { return a; }
float getB() { return b; }
};
class Widget
{
public:
void doStuff(Stuff s)
{
doStuff(s.getA(), s.getB()); //error: no matching function for call to 'Widget::doStuff(int, float)'
}
};
int main()
{
Widget w;
w.doStuff(Stuff(42, 3.14f));
return 0;
}
In this example, void doStuff(int a, float b) is the old C-function. Because in my real code, its equivalent is in an external library/header file, I cannot change its name. Next, Stuff is a container for keeping the values void doStuff(int a, float b) needs. The important things happen in Widget: void Widget::doStuff(Stuff s) should be the actual wrapper. I now expect doStuff(s.getA(), s.getB()) to call the old C-style function void doStuff(int a, int b) but the compilation fails with the given error.
Is it possible to make this code work without changing the name of the both doStuff functions? One option I already thought of is surrounding void doStuff(int a, float b) by some namespace. This works, but seems like very bad practice to me.
My compiler is mingw-w64 with g++ 5.2.0, so C++11 and C++14 are available.
The doStuff(Stuff s) method in your class hides the global function doStuff(int a, float b). If you want to call the global doStuff function, you have to use the scope resolution operator :: (::doStuff(s.getA(), s.getB());)
Try making your call like this:
::doStuff(s.getA(), s.getB());
I am trying to understand object oriented programming using c++. The following is a minimal example for which the result is not what I naively expect:
#include <iostream>
class B {
public:
B (int val) : val(val) {;}
int get_val() { return val; }
int set_val(int a) { val = a; }
private:
int val;
};
class A {
public:
A (B b) : b(b) {;}
B get_b() { return b; }
private:
B b;
};
int main(){
B b_main(5);
std::cout << b_main.get_val() << std::endl; // Prints 5, which makes sense
A a_main(b_main);
std::cout << a_main.get_b().get_val() << std::endl; // Prints 5, which makes sense
a_main.get_b().set_val(2);
std::cout << a_main.get_b().get_val() << std::endl; // Why does this not print 2?
return 0;
}
The last cout statement does not make sense to me. In the second to last line, I set the value of the object to be 2, so why does this not print 2? Looking at some similar questions on Stack Exchange, I found some suggestions to make A and B be friends of each other. I tried adding friend class A in class B and friend class B in class A, but this did not work. In my understanding, adding the friend statements should be unnecessary since I have the get_b() method in class A. I found some suggestions to try passing the object of type B in by reference to the constructor of A: A (B& b) : b(b) {;} but this did not work either.
Can anyone explain to me why the program is not producing the intended result and also how to obtain the desired result (that is, the last cout statement prints 2)?
Note: I also experimented with the following. I made the private variable b of class A be public:
#include <iostream>
class B {
public:
B (int val) : val(val) {;}
int get_val() { return val; }
int set_val(int a) { val = a; }
private:
int val;
};
class A {
public:
A (B b) : b(b) {;}
B b; // This is now public
//B get_b() { return b; } // This is no longer needed
private:
};
int main(){
B bmain(5);
std::cout << bmain.get_val() << std::endl;
A amain(bmain);
std::cout << amain.b.get_val() << std::endl;
amain.b.set_val(2);
std::cout << amain.b.get_val() << std::endl; // Works!
return 0;
}
And now I obtain the desired result. Is this how the code should be implemented as opposed to the first code snippet? I would like to have a get_b() method as in the first code snippet, but if this is not the correct way of going about this, please let me know.
In the second to last line, I set the value of the object to be 2, so why does this not print 2?
Because you return a copy of the B object in a_main with the get_b() method. What happens is that the b variable in a_main is copied, i.e. another object of class B, identical to the b member, is created, and returned to the caller. Then, that new B object is modified. But it has no connection to the original b in a_main. This has little to do with visibility and member access.
However, in the second example, you expose the b member in a_main and directly operate on that object without making a copy of it, thus the successful result. What the public modifier changes is that it allows you to access the b object directly, hence the effect.
I found some suggestions to try passing the object of type B in by reference to the constructor of A: A (B& b) : b(b) {;} but this did not work either.
That isn't going to work. What happens when you do so, is that the A::b is initialized using the value that is passed by reference, true. But the reference only leads to no additional copy of b passed to the constructor being made. This reference does not create a link between the b passed to the constructor and A::b. It's on the other end, so to say.
By the way, A (B& b) : b(b) {;} that the c'tor parameter name is identical to the member name is a bad practice. It's a good idea to have them named similarly, but still, add e.g. an underscore: A (B& _b) : b(_b) {;}
If you want to achieve the same result in the first snippet, return a reference to b like so:
B& get_b() { return b; }
Still, this is undesirable, because you expose a private member of class A just to allow clients of A to modify a certain property of that member. Better provide a method in A to set the val property of A::b without giving full access to A::b.
Definitely see this: What's the difference between passing by reference vs. passing by value?
and maybe this: Java and C++ pass by value and pass by reference
because I have a feel that you're coming from Java and expect pass-by-reference in C++ by default.
get_b returns a copy of your private variable b, not the actual variable. If you want to be able to access it, you need to return a reference to b so that the returned value can be manipulated. Your get_b definition should look like this:
B& get_b() { return b; }
if that is what you expect to do. However, this is not usually a desirable solution. If you are going to be actively changing the value of b you should write a set_b function to manipulate the variable. And if you are really working with the variable a lot, reading and writing values to it, you should keep it public for fast access.
Just for the sake of completeness, you can solve this problem as a C programing problem rather than using all the fancy references in C++ programing. When you get b_main from a_main, the returned object does not occupy the same memory address.
#include <iostream>
class B {
public:
B (int val) : val(val) {;}
int get_val() { return val; }
int set_val(int a) { val = a; }
private:
int val;
};
class A {
public:
A (B b) : b(b) {;}
B get_b() { return b; }
private:
B b;
};
int main(){
B b_main(5);
B* addrb = &b_main;
std::cout << b_main.get_val() << std::endl; // Prints 5, which makes sense
std::cout<<"Address of b_main: "<<addrb<<std::endl;
A a_main(b_main);
B bt = a_main.get_b();
addrb = &(bt);
std::cout << a_main.get_b().get_val() << std::endl; // Prints 5, which makes sense
std::cout<<"Address of a_main.get_b(): "<<addrb<<std::endl;
a_main.get_b().set_val(2);
std::cout << a_main.get_b().get_val() << std::endl; // Why does this not print 2?
return 0;
}
Notice the difference in address of the new cout statements. One way to fix this is to return pointers rather than b itself. i.e.
#include <iostream>
class B {
public:
B (int val) : val(val) {;}
int get_val() { return val; }
int set_val(int a) { val = a; }
private:
int val;
};
class A {
public:
A (B b) : b(b) {;}
B* get_b() { return &b; }
private:
B b;
};
int main(){
B b_main(5);
//B* addrb = &b_main;
std::cout << b_main.get_val() << std::endl; // Prints 5, which makes sense
//std::cout<<"Address of b_main: "<<addrb<<std::endl;
A a_main(b_main);
//B bt = a_main.get_b();
//addrb = &(bt);
std::cout << a_main.get_b()->get_val() << std::endl; // Prints 5, which makes sense
//std::cout<<"Address of a_main.get_b(): "<<addrb<<std::endl;
a_main.get_b()->set_val(2);
std::cout << a_main.get_b()->get_val() << std::endl; // Why does this not print 2?
return 0;
}
I'm using base-from-member idiom and I now stuck with copy/move constructors for them. Suppose following code:
#include <iostream>
#include <string>
#include <boost/lexical_cast.hpp>
using namespace std;
struct A // base class
{
A(string &s) : s(s), c(0) { };
A(const A &a) : s(a.s), c(a.c) { };
void print() { cout << s << endl; c++; }
int print_count() { return c; }
string &s;
int c;
};
struct B_base // this class will be initialized before A
{
B_base(int i)
{
s = boost::lexical_cast<string>(i);
}
B_base(const B_base &other) : s(other.s) { };
string s;
};
struct B : B_base, A // main class
{
B(int i) : B_base(i), A(B_base::s) { }
B(const B &other) : B_base(other), A(other) { } // <-- problem here
using A::print;
using A::print_count;
};
int main()
{
B b(10);
b.print(); // prints '10'
cout << b.print_count() << endl; // prints '1'
B b1(b);
b1.print(); // prints '10'
A &a = b;
a.s = "FAIL"; // we modify b, not b1 here!
b1.print(); // but b1 prints 'FAIL' here --- error (it should still print '10')
cout << b.print_count() << " " << b1.print_count() << endl; // prints '1 3'
return 0;
}
Problem here is that reference A.s (which is point to B_base::s) is copied from one instance to another, while it should be modified to point to another B_base::s. Things may be even worse, if previous instance is go out of scope ending with dangling references.
My question is: how can I make correct copy of class with base-from-member idiom? (I think move constructor will be similar to copy one, right?)
The base-from-member idiom you are exercising in this case means: you want a class B derived from A with have to be initialized using a member of B (with is: string s).
B b(10);
B b1(b); // B(const B &other) : B_base(other), A(other) { }
// now A::s in b1 is a ref to b.s
A &a = b;// and a.s is a ref to b.s too.
a.s = "FAIL"; // we modify b, and A::s in b1 to!
This problem can be solved making the copy constructor:
B(const B &other) : B_base(other), A(B_base::s) { }
Also, having A::s and B_base::s with the same name, make thing more difficult to understand.
EDIT: As a class designer, you have to decide with is the exact meaning of your copy constructor.
For example, in this case you may want to keep track (with A::c) of the number of printing of each newly create object A. The copy constructor I proposed do it.
But if you want to keep track of all printing of the original string thing are more complex. Just note that if you copy the old A::c to the new A it will be correct initialized, bur not cross actualized when the the printing of the same original string is made using different copies of A. If this is not a problem you can modify the constructors:
A(string &s, int _c=0) : s(s), c(_c) { };
...
B(const B &other) : B_base(other), A(B_base::s, other.c) { }
I am puzzled by some issues when trying to design interacting classes.
If a class A needs some data from class B, either in the form of a pointer or standard container format, (or even lets become more ambitious and say in the form of some shared_ptr members to stl containers.), my way is to use a function that returns the same kind of arguments and design class B methods with conforming arguments? Are there a general rules of thumb for designing interacting classes and share data between these classes?
Could you please draw a general scheme for some common situations that are generally encountered in practice(and along some examples are appreciated)? I guess I should read some examples on class interaction in C++, any pointers on this are also appreciated?
A small sample could be:
#include <iostream>
#include <vector>
#include <iterator>
#include <cassert>
using namespace std;
class A{
public:
A(int s, int val):sz(s), val(val), v(new vector<int>){}
int fill_vector(){
for(int k=0;k!=sz;++k)
v->push_back(val);
return 0;
}
~A(){
cout << "Dtor is deleting the pointer to vector\n";
delete v;
}
vector<int>* get_pointer_to_vector_in_A(){ return v; }
private:
int sz, val;
vector<int> *v;
};
class B{
public:
B(){} // does nothing basically
int print_vector_contents_from_A( vector<int> *v_from_A ) const
{
assert(!v_from_A->empty());
copy(v_from_A->begin(), v_from_A->end(),
ostream_iterator<int>(cout, "\n") );
}
};
int main()
{
A a(10, 4);
a.fill_vector();
B b;
b.print_vector_contents_from_A( a.get_pointer_to_vector_in_A() );
return 0;
}
It rather depends on what A is, conceptually. If A can be validly viewed as a sequence of int, then I'd implement size_t size() const and int &operator[](size_t) (+ its const counterpart) on it. These can just delegate their activities to v.size and v[] or v.at.
In B, you can then define
static void B::print_contents(A const &a)
{
for (size_t i=0; i < a.size(); i++)
std::cout << a[i] << '\n';
}
A member that returns an std::vector<int>* breaks encapsulation: you can never change the implementation of A away from std::vector<int> except with very ugly hacks to ensure get_pointer_to_vector_in_A still works with the same semantics.
One great one-directional way to do this is:
class A {
public:
void fill_vector();
int vec_size() const { return vec.size(); }
int get_data(int i) const { return vec[i]; }
};
class B {
public:
B(A &a) : a(a) { }
void init() { a.fill_vector(); }
void fetch_and_print()
{ for(int i=0;i<a.vec_size();i++) std::cout << a.get_data(i); }
private:
A &a;
};
int main() {
A a;
B b(a);
b.init();
b.fetch_and_print();
}
The constructor parameter for class B is the important bit.