I am trying to do a deep copy of class B, but A doesn't get set.
Why does b3->print return a garbage number instead of 1?
From what I understand, b2 and b3 are both pointing to the same A object. but I created a new object on the heap with B's copy constructor. so why are they both still poiting to the same object?
I hope this makes sense.
#include <cstdlib>
#include <iostream>
using namespace std;
class A{
int num;
public:
A(int n):num(n){ cout<< "A "<< num << " constructor" <<endl;}
~A(){ cout<< "A "<< num <<" destructor. " <<endl; }
int print(){
cout<< num<< endl;
}
};
class B{
A *a;
int num;
public:
B(int n):num(n){
a = new A(n);
cout<< "B "<< num <<" constructor" <<endl;
}
~B(){
delete a;
cout<< "B "<< num <<" destructor"<<endl;
}
// Copy contructor
B(const B & b): a(new A(b.num)){
}
<strike>int<\strike> void print(){
cout<< num << endl;
}
int get_num(){
return num;
}
};
int main(int argc, char *argv[])
{
B *b2 = new B(1);
B *b3(b2);
b2->print();
delete b2;
b3->print();
system("PAUSE");
return EXIT_SUCCESS;
}
B *b3(b2); doesn't do what you think.
It's equivalent to B* b3 = b2. The pointers will point to the same location. When you do delete b2;, you're also freeing the memory pointed to by b3.
To do a deep copy, do:
B* b3 = new B(*b2);
There's also undefined behaviour here:
int print(){
cout<< num << endl;
}
because you never return. Change the return type to void.
To get the value expected:
B(const B & b): a(new A(b.num)), num(b.num){
}
Other answers to this question will explain about how pointers work, but you should also understand that not using pointers is a better solution. C++'s default behaviors work well with value semantics. If you hold objects by value then the default copy ctor and assignment operators will do a 'deep copy'.
class B{
A a;
int num;
public:
B(int n): a(n), num(n){
cout<< "B "<< num <<" constructor" <<endl;
}
void print(){
cout<< num << endl;
}
int get_num(){
return num;
}
};
Also, if you do use owning pointers you should usually use smart pointers.
here you are not copying b2
B *b3(b2);
instead you are making b3 point to b2
you should have
B *b3 = new B(*b2);
I think you probably intended to write something like this:
#include <iostream>
class A
{
public:
A(int n) : num_(n) {}
void print() { std::cout << num() << std::endl; }
int num() const { return num_; }
private:
int num_;
};
class B
{
public:
B(int n) : a(n) {}
int num() const { return a.num(); }
private:
A a;
};
int main()
{
B b(1);
B b2 = b; // deep copy
}
As you can see:
B doesn't have its own num_ member. Duplication should be avoided.
There's no need to implement the copy constructor or assignment operator (rule-of-three).
Not need to use new here.
There is no such things as shallow/deep copy in c++. You either have values or pointers/references that get copied, and that fully defines the semantics of the copy operation.
Related
Why the following code produces garbage value instead of product of two numbers? While debugging many times destructor is being called. Somebody please explain me what is happening behind the scene. There are two classes A and B. A is inherited by the base class B and the operator "%" is overloaded to produce the product of two numbers of two different classes but the desired output is not obtained when called from the main().
#include <iostream>
using namespace std;
class B;
class A
{
public:
int x;
A()
{
}
~A()
{
}
friend int operator/(A, B);
void acceptValue();
private:
};
class B :public A
{
public:
int y;
B()
{
}
void acceptValueY()
{
cout << "Enter the value of y: ";
cin >> y;
return;
}
~B()
{
}
friend int operator/(A, B);
private:
};
int operator/(A obj1, B obj2)
{
return obj1.x * obj2.y;
}
void A::acceptValue()
{
cout << "Enter the value of x: ";
cin >> x;
return;
}
int main()
{
A ob;
B baseObj;
ob.acceptValue();
baseObj.acceptValueY();
cout<<baseObj / (ob, baseObj);
}
Check inline comments for answer
#include <iostream>
using namespace std;
class B;
class A
{
public:
int x;
A()
{
}
/*A(const A& a)
{
}*/
~A()
{
}
friend int operator/(A, B);
void acceptValue();
private:
};
class B :public A
{
public:
int y;
B() // Will invoke A constructor. But value of member x in A object will be garbage as it is uninitialized.
{
}
void acceptValueY()
{
cout << "Enter the value of y: ";
cin >> y;
return;
}
~B() // Will invoke A destructor
{
}
friend int operator/(A, B);
private:
};
int operator/(A obj1, B obj2)
{
return obj1.x * obj2.y;
} // Destructor of A and B (and hence A again) will get called.
int test(A obj1, B obj2)
{
return obj1.x * obj2.y;
}
void A::acceptValue()
{
cout << "Enter the value of x: ";
cin >> x;
return;
}
int main()
{
A ob;
B baseObj;
ob.acceptValue();
baseObj.acceptValueY();
// This way of invocation is causing garbage value. Firts arument is of type A.
// So copy construction of A type object will happen from baseObj.
// But as B constructor causes default constrcution of A, value of member x is garbage.
//int val = baseObj / (ob, baseObj);
// Correct way of invocation
int val = ob / baseObj; // It will show compute right val value. Will invoke copy constructor of A and B as they are being passed by value.
cout << val;
} // Destructor of A and B (hence again A) will get called.
First, the comma-operator will evaluate the expression (ob, baseObj) and discard all but the last statement, so it evaluates to baseObj.
You end up with cout << baseObj / baseObj and the operator int operator/(A obj1, B obj2) effectively calculates baseObj.x * baseObj.y.
The randome values appear, because baseObj.x was never initialized and thus contains garbage.
Extra line of code can be added only to the place where '>>' sign is present.
My targeted input and output is as follows:
Input: 15
Output : 16:15:17:16:
I need help only in
cout << r.get() << ":";
part. An explanation would be helpful.
#include <iostream>
using namespace std;
class A {
int i;
public:
A(int ai) : i(ai) {}
int get() const { return i; }
void update() { ++i; }
};
class B {
int i;
public:
B(int ai) : i(ai) {}
int get() const { return i; }
//>>
operator A() {return A(i);}
void update() { ++i; }
}; // End of class B
int main() {
int i;
cin >> i;
A a(i++);
B b(i);
const B &r = static_cast<B>(a);
a.update();
cout << a.get() << ":";
cout << r.get() << ":";
const A &s = static_cast<A>(b);
b.update();
cout << b.get() << ":";
cout << s.get() << ":";
return 0;
}
You cannot solve the asker's problem by modifying a conversion operator in class B. B's conversion operators only tell the constructor how to make another datatype out of a B. To do this with a conversion operator, the operator needs to be in class A.
class B; // forward declaration of B so that A knows it exists
class A
{
int i;
public:
A(int ai) :
i(ai)
{
}
int get() const
{
return i;
}
void update()
{
++i;
}
operator B(); // cannot implement the function yet because we do not have a
// complete definition of B. Without a definition of B we cannot
// construct B excluding forward defined helper functions that are
// implemented later, gaining us nothing.
};
Then later after B is fully defined,
A::operator B()
{
return B(i); // now we have enough information to construct a B
}
Note: We can reduce some of this messiness by moving the definition of B to before the definition of A. Unfortunately this makes the code required to support the
const A &s = static_cast<A>(b);
that comes later in the code require forward declaration of A and the implementation of the B to A conversion operator outside the definition of B.
An alternative is adding a constructor to B that takes an A
B::B(const A& a): i(a.get())
{
}
and vice-versa for A.
I try to figure out output of the program without running. I'm stuck some points that first when I put a breakpoint after const A g1; , how come the program print output const A 2 5 ? Second, is B b1(a1); same as B b1 = a1; in this code ? Thirdly, when a B obj is constructed by taking parameter an object of A, as you see A a is private member in A class. The p function doesn't execute. How come? I think it should be executed. The last one, when a B obj is executed(constructed), "const B" string literal should be printed screen out. But, It's printed just for B b1(a1);. Why not also B b2(b1); and B b3 = b2;?
#include <iostream>
using std::cout;
class A {
public:
A(int i = 10){ t = i; f(); p("const A ");}
static void f(){ ++s;}
void g() { ++t; p("func g ");}
void operator++() {p("op++ 1 ");}
void operator++(int) {p("op++ 2 ");}
private:
void p(const char *t) const
{cout << t << s << " "
<< this->t << "\n";
}
int t;
static int s;
};
const A g1; // Global object
int A::s = 0;
class B {
public:
B(A& t) : a(t)
{ cout << "const B\n"; }
private:
A a;
};
class C{
public:
C(B& t) : b(t)
{
cout << "const C\n";
}
private:
B b;
};
void h(A a){
++a;
B b(a);
a++;
}
static C g_c( *(new B( *(new A(5) ) ) ) );
int main(){
cout << "--------\n";
{
A::f();
A a;
a.f(); a.g();
}
cout << "--------\n";
{
A a;
h(a);
}
cout << "--------\n";
{
A a1;
A a2(a1);
A a3 = a1;
a2 = a1;
cout << "--------\n";
B b1(a1);
B b2(b1);
B b3 = b2;
b2 = b1;
cout << "--------\n";
}
cout << "--------\n";
return 0;
}
You cannot put a breakpoint outside a function body. There is nothing there. Your global variables are initialised before main is executed. If you want to break the construction of global A g1 put a breakpoint in A's constructor.
B b1(a1); is indeed the same as B b1 = a1;
The p function does not execute because the new A object is copy constructed. It is not your constructor that gets executed but a copy constructor generated by the compiler. If this copy constructor does not do what you'd like it to do, write your own.
Same answer, the first B object is constructed with your constructor, the others are copy constructed.
I have following code on c++:
#include <iostream>;
#include <vector>;
class A
{
public:
A(int n = 0) : m_n(n) { }
public:
virtual int value() const { return m_n; }
virtual ~A() { }
protected:
int m_n;
};
class B
: public A
{
public:
B(int n = 0) : A(n) { }
public:
virtual int value() const { return m_n + 1; }
};
int main()
{
const A a(1);
const B b(3);
const A *x[2] = { &a, &b };
typedef std::vector<A> V;
V y;
y.push_back(a);
y.push_back(b);
V::const_iterator i = y.begin();
std::cout << x[0]->value() << x[1]->value()
<< i->value() << (i + 1)->value() << std::endl;
system("PAUSE");
return 0;
}
The compiler returned result: 1413.
I am little bit confused, because I thought the right result would be 1414 (as the function virtual). How do you explain this program behavior?
You are slicing the object, in order to get polymorphism you need to use either a pointer or a reference. This example keeping as close as possible to your original example and using a pointer will act as you wanted:
const A a(1);
const B b(3);
typedef std::vector<const A*> V;
V y;
y.push_back(&a);
y.push_back(&b);
V::iterator i = y.begin();
std::cout << (*i)->value() << std::endl ;
++i ;
std::cout << (*i)->value() << std::endl ;
To show briefly how the object slicing works here:
const A a(1);
const B b(3);
std::vector<A> y; // so y contains objects of type A
y.push_back(a); // y[0] is copy-constructed from a
y.push_back(b); // y[1] is copy-constructed from b
Note that in both push_back calls, it's always an A being constructed, via the automatically-generated A::A(const A&) copy constructor.
Note also that a B is-a A, which is to say b can be implicitly cast to an A and passed into the same copy-constructor.
So, y[1] is an instance of A with the m_n value copied from b, but its virtual function is still A::value. If you have constructor B::B modify the value when it is initialized, instead of when it is returned, you'll see the result you expect.
The following piece of code gets compiled under g++ 4.6.3 for Linux
#include <iostream>
class A {
public:
int x;
std::string c;
A(int x,std::string c):x(10),c("Hi"){
}
~A(){
std::cout << "Deleting A()" << std::endl;
}
};
class B : public A {
public:
B():A(20,"Hello"){
}
~B(){
std::cout << "Deleting B()" << std::endl;
}
};
int main(){
B o;
std::cout << o.x << std::endl;
std::cout << o.c << std::endl;
return(0);
}
but it does not do what is supposed to do, the type B is not able to change the values of that 2 variables that it inherit from A.
Any explanations about why this doesn't work properly ?
Your base constructor takes those values...and completely disregards them!
Change this:
A(int x,std::string c):x(10),c("Hi"){}
to this:
A(int x,std::string c):x(x),c(c){}
There seems to be some confusion about what you want and how to achieve this.
If I got you right this is what you want:
class A {
public:
int x;
std::string c;
//default initization of A
A():x(10), c("Hi") {}
//initializing the values of A via parameters
A(int x,std::string c):x(x),c(c){}
~A(){
std::cout << "Deleting A()" << std::endl;
}
};
class B : public A {
public:
B():A(20,"Hello"){
}
~B(){
std::cout << "Deleting B()" << std::endl;
}
};
So in this example:
int main()
{
A a;
A a1(2, "foo");
B b;
return 0;
}
a.x == 10, a.c == "Hi"
a1.x == 2, a1.c == "foo"
b.x == 20, b.c == "Hello"
OK, I don't understand what exactly you want and why, but here's a suggestion, with C++11, you can do the following:
struct Base {
int a;
float b;
};
struct Derived: public Base {
Derived(): Base{1,1.0} {}
};
int main() {
Derived d;
}
as long as the base is a POD type.
I'd still prefer A(int x = 10,std::string c = std::string("Hi")):x(x),c(c){...} though.
IMHO, you need to review if you really need that much control over your base class in the first place. You're not really supposed to micro-manage a class from the outside like that, it's an indication of a flaw in your class hierarchy.