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;
}
Related
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.
Can a class that contains only one attribute be converted into the type of the attribute?
This example prints 1 as intended. But is it guaranteed to work?
class A {
private:
int x = 1;
};
int main()
{
A a;
cout << *((int*)&a) << endl; // (1)
cout << *(int*)(((char*)&a)+offsetof(A, x)) << endl; // (2) //requires x to be public
return 0;
}
EDIT:
Or is there another way to access a.x without modifying A?
It cannot be guaranteed (at least I found nothing in C++ specifications about it) but it is true that common compiler implementation put first element of a class or struct at first place, so that it has same address as the struct itself.
But you will get a working case of a general Undefined Behaviour. Is it acceptable or not depends on your actual requirements. Examples :
this code will only run in a limited environment (your own machine or a few on which you have control) => you just have to document the fact and test for every change of compiler version
the code will be included in a non sensible application that will only deployed in binary form => document it in red flashing font but you can contemplate using it
this code will be included in an sensible application that will be deployed to many different systems => forget it
The best way to do that is implementing the corresponding cast operator :
class A
{
private:
int x = 1;
public:
operator int () const { return this->x; }
};
int main()
{
A a;
std::cout << (int)a << std::endl;
return 0;
}
Another solution can be the following. It's less intrusive in the code, but I prefer the previous one.
class A
{
public:
A(int x_) : x(x_) {}
private:
int x;
friend class A_Caster;
};
class A_Caster
{
private:
const A& a;
public:
A_Caster(const A& a_) : a(a_) {}
operator int () const { return this->a.x; }
};
int main()
{
A a(10);
std::cout << (int)A_Caster(a) << std::endl;
return 0;
}
Lately I've been working in some project and the thing is that we've encountered a situation in which we need to be able to do stuff like this.
#define TYPED(Type) \
virtual Type *typedThis() const { return (Type*) this; }
class A {
public:
TYPED(A)
virtual void describe() { std::cout << "I am type A\n"; }
static int x;
};
int A::x = 1;
class B : public A {
public:
TYPED(B)
virtual void describe() { std::cout << "I am type B\n"; }
static int x;
};
int B::x = 2;
int
main(int argc, char** argv)
{
B* b = new B();
A* b2 = b;
b->describe();
b2->describe();
std::cout << b->typedThis()->x << std::endl;
std::cout << b2->typedThis()->x << std::endl; // AQUI DEBERIA DAR 2 !! :c
}
This is of course just a toy example. The basic idea of what we would like to do is to define a function typedThis() who does the casting of the pointer into the correct type and then access to the correct variable x, and printing out 2 instead of 1.
However, the output is the following:
I am type B
I am type B
2
1 //Here should also be 2
What I find really interesting is that the virtual method describe() seems to be working the way we want. Therefore, I could infer that the method typedThis() is also working the way we would like to. But if so, why does C++ see this pointer as an A* instead of an B*. If C++ saw this pointer like a B* then it would have used the correct variable x. Can someone explain this to me?
I tried using CRTP, however I don't feel like this would make things easier, because in the project we will be using a lot (A LOT) of different classes who derive between them constantly, I saw some articles of how to use CRTP when having multiple inheritance, however they are really messy and hard to integrate with what we have so far.
I removed all distractions from the example:
class A {
public:
virtual A *typedThis() const { return (A*) this; }
static int x = 1;
};
class B : public A {
public:
virtual B *typedThis() const { return (B*) this; }
static int x = 2;
};
int main()
{
B* b1 = new B;
A* b2 = b1;
std::cout << b1->typedThis()->x << "\n";
std::cout << b2->typedThis()->x << "\n";
}
typedThis doesn't do anything.
b1->typedThis() returns a B* which points to a B.
Likewise, b1 itself is a B* which points to a B.
b2->typedThis() returns an A* which points to a B.
Likewise, b2 itself is an A* which points to a B.
So b1->typedThis() is the same as b1 and b2->typedThis() is the same as b2, and the last two lines of the example are equivalent to the following:
std::cout << b1->x << "\n";
std::cout << b2->x << "\n";
Also take note that your C-style casts discard the const qualifiers of the objects.
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 stumbled upon something similar today, and subsequently tried a few things out and noticed that the following seems to be legal in G++:
struct A {
int val_;
A() { }
A(int val) : val_(val) { }
const A& operator=(int val) { val_ = val; return *this; }
int get() { return val_; }
};
struct B : public A {
A getA() { return (((A)*this) = 20); } // legal?
};
int main() {
A a = 10;
B b;
A c = b.getA();
}
So B::getB returns a type A, after it as assigned the value 20 to itself (via the overloaded A::operator=).
After a few tests, it seems that it returns the correct value (c.get would return 20 as one may expect).
So I'm wondering, is this undefined behavior? If this is the case, what exactly makes it so? If not, what would be the advantages of such code?
After careful examination, with the help of #Kerrek SB and #Aaron McDaid, the following:
return (((A)*this) = 20);
...is like shorthand (yet obscure) syntax for:
A a(*this);
return a.operator=(20);
...or even better:
return A(*this) = 20;
...and is therefore defined behavior.
There are a number of quite separate things going on here. The code is valid, however you have made an incorrect assumption in your question. You said
"B::getA returns [...] , after it as assigned the value 20 to itself"
(my emphasis) This is not correct. getA does not modify the object. To verify this, you can simply place const in the method signature. I'll then fully explain.
A getA() const {
cout << this << " in getA() now" << endl;
return (((A)*this) = 20);
}
So what is going on here? Looking at my sample code (I've copied my transcript to the end of this answer):
A a = 10;
This declares an A with the constructor. Pretty straightfoward. This next line:
B b; b.val_ = 15;
B doesn't have any constructors, so I have to write directly to its val_ member (inherited from A).
Before we consider the next line, A c = b.getA();, we must very carefully consider the simpler expression:
b.getA();
This does not modify b, although it might superfically look like it does.
At the end, my sample code prints out the b.val_ and you see that it equals 15 still. It has not changed to 20. c.val_ has changed to 20 of course.
Look inside getA and you see (((A)*this) = 20). Let's break this down:
this // a pointer to the the variable 'b' in main(). It's of type B*
*this // a reference to 'b'. Of type B&
(A)*this // this copies into a new object of type A.
It's worth pausing here. If this was (A&)*this, or even *((A*)this), then it would be a simpler line. But it's (A)*this and therefore this creates a new object of type A and copies the relevant slice from b into it.
(Extra: You might ask how it can copy the slice in. We have a B& reference and we wish to create a new A. By default, the compiler creates a copy constructor A :: A (const A&). The compiler can use this because a reference B& can be naturally cast to a const A&.)
In particular this != &((A)*this). This might be a surprise to you. (Extra: On the other hand this == &((A&)*this) usually (depending on whether there are virtual methods))
Now that we have this new object, we can look at
((A)*this) = 20
This puts the number into this new value. This statement does not affect this->val_.
It would be an error to change getA such that it returned A&. First off, the return value of operator= is const A&, and therefore you can't return it as a A&. But even if you had const A& as the return type, this would be a reference to a temporary local variable created inside getA. It is undefined to return such things.
Finally, we can see that c will take this copy that is returned by value from getA
A c = b.getA();
That is why the current code, where getA returns the copy by value, is safe and well-defined.
== The full program ==
#include <iostream>
using namespace std;
struct A {
int val_;
A() { }
A(int val) : val_(val) { }
const A& operator=(int val) {
cout << this << " in operator= now" << endl; // prove the operator= happens on a different object (the copy)
val_ = val;
return *this;
}
int get() { return val_; }
};
struct B : public A {
A getA() const {
cout << this << " in getA() now" << endl; // the address of b
return (((A)*this) = 20);
// The preceding line does four things:
// 1. Take the current object, *this
// 2. Copy a slice of it into a new temporary object of type A
// 3. Assign 20 to this temporary copy
// 4. Return this by value
} // legal? Yes
};
int main() {
A a = 10;
B b; b.val_ = 15;
A c = b.getA();
cout << b.get() << endl; // expect 15
cout << c.get() << endl; // expect 20
B* b2 = &b;
A a2 = *b2;
cout << b2->get() << endl; // expect 15
cout << a2.get() << endl; // expect 15
}