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.
Related
given following piece of code:
#include <iostream>
class A
{
public:
int a;
A() : a(0) {}
};
class B : public A
{
public:
int b;
B(int b) : b(b) {}
B() {}
};
int main()
{
B new_b;
new_b.b = 5;
new_b.a = 4;
std::cout << new_b.a << std::endl;
new_b = B(2); // at this point I want to keep new_b.a
std::cout << new_b.a << std::endl;
}
What is the correct way of achiving this? I know I could overload B's assignment operator and only take over new_b.b here, but is this the proper way of keeping B.a's value?
Thanks for any help on this issue.
Kind Regards,
Steve
#include <iostream>
class A
{
public:
int a;
A() : a(0) {}
};
class B : public A
{
public:
int b;
B(int b) : b(b) {}
B() : b(0) {}
B operator = (B ob) // using operator overloading, the = operator is overloaded
{
b = ob.b;
return b;
}
};
int main()
{
B new_b;
new_b.b = 5;
new_b.a = 4;
std::cout << new_b.a << std::endl;
new_b = B(2); /* Previously a new object of class B with parameterized constructor was made and copied to new_b which created a new object of class A everytime.
Now as the = operator is overloaded, it just copies the value(2) into new_b without creating a new object of class B or A thus the original value of A::a is preserved*/
std::cout << new_b.a << std::endl;
std::cin.get();
}
Hi this is my first time posting an answer, hope I was clear enough for you to understand, if you have a problem I'd be happy to help again
I have an interesting problem to deal with. Is there any way to call derived class functions with base class pointer without virtual pointers? IMHO, I do not think so but would like to clear with experts.
Consider this example:
class B {
public:
int a;
int b;
int get_a() { return a };
int get_b() { return b };
B() : a(1), b(2) { }
};
class D : public B {
public:
int a;
int b;
int get_a() { return a };
int get_b() { return b };
D() : a(3), b(4) { }
};
int main() {
Base* b = new Base;
std::cout << b->get_a() << std::endl; // Gives 1
std::cout << b->get_b() << std::endl; // Gives 2
// Do something here which instantiates Derived and can call Derived functions using base class pointers.
// Maybe Base\* b = new Derived();
// But doing b->get_a() should call Derived class function get_a.
std::cout << <some_base_class_pointer_after_doing_something>->get_a() << std::endl; // Should give 3
std::cout << <some_base_class_pointer_after_doing_something>->get_b() << std::endl; // Should give 4
}
Is there any possible way? reinterpret_cast or anything else?
I do not want to use virtual since vptr comes into the picture and increases the memory by 8 bytes(depends) per object. Very frequently, I can have big number of B type objects. Say, 1 million objects of B type, I do not want my program memory to go by 1m x 8 bytes. Instead, I would rather not have virutal/vptr in such huge cases.
I would be happy to write more details if needed.
You can write:
Base* b = new Derived;
Derived *d = static_cast<Derived *>(b);
std::cout << d->get_b() << '\n';
Of course, this would cause undefined behaviour if you tried it on a b that did not actually point to a Derived or child class of such. If you are in general not sure what the pointer points to, and you don't want to use vtables, you'll need to manually implement something to give you that information (e.g. a member variable of Base with type information).
Since I could not get any answer from anyone, let me float an option here which I have thought of. This might be a hack though. I am open for correction/comments and criticism as well. :)
The deal is to do reinterpret_cast in the base class functions.
#include <iostream>
#include <vector>
bool preState = true;
class Derived;
class Base;
class Base {
public:
unsigned char a;
int b;
Base() : a('a'), b (2) { };
unsigned char get_a() const;
int get_b() const;
} __attribute__ ((__packed__)) ;
class __attribute__ ((__packed__)) Derived : public Base {
public:
unsigned char c;
int d;
Derived() : c('c'), d(4) { };
unsigned char get_a() const;
int get_b() const;
};
unsigned char Base::get_a() const {
if (preState) {
return a;
} else {
const Derived* d = reinterpret_cast<const Derived*>(this);
return d->get_a();
}
}
int Base::get_b() const {
if (preState) {
return b;
} else {
const Derived* d = reinterpret_cast<const Derived*>(this);
return d->get_b();
}
}
unsigned char Derived::get_a() const {
return c;
}
int Derived::get_b() const {
return d;
}
int main() {
std::vector<Base*> bArray;
bArray.push_back(new Base());
bArray.push_back(new Base());
std::vector<Base*>::iterator bArrayIt = bArray.begin();
for (; bArrayIt != bArray.end(); ++bArrayIt) {
std::cout << (*bArrayIt)->get_a() << " ";
std::cout << (*bArrayIt)->get_b() << std::endl;
}
preState = false;
std::vector<Base*> dArray;
bArrayIt = bArray.begin();
for (; bArrayIt != bArray.end(); ++bArrayIt) {
// Write copy constructor in Derived class which copies everything from
// base object to Derived object
Base* b = new Derived();
dArray.push_back(b);
}
std::vector<Base*>::iterator dArrayIt = dArray.begin();
for (; dArrayIt != dArray.end(); ++dArrayIt) {
std::cout << (*dArrayIt)->get_a() << " ";
std::cout << (*dArrayIt)->get_b() << std::endl;
}
}
The output of this would be:
a 2 // Base class get_a() and get_b()
a 2 // Base class get_a() and get_b()
c 4 // Derived class get_a() and get_b()
c 4 // Derived class get_a() and get_b()
At the last line myA = foo(myOtherB);, the function will return type an object of type A, thus; it will be like saying `myA = input, But why is the copy constructor is being?
output:
B foo()
A copy ctor //what calls this?
A op=
For a copy constructor to be called we will have to use the assignment operator during initialization such as: B newB = myOtherB;
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A ctor" << endl; }
A(const A& a) { cout << "A copy ctor" << endl; }
virtual ~A() { cout << "A dtor" << endl; }
virtual void foo() { cout << "A foo()" << endl; }
virtual A& operator=(const A& rhs) { cout << "A op=" << endl; }
};
class B : public A {
public:
B() { cout << "B ctor" << endl; }
virtual ~B() { cout << "B dtor" << endl; }
virtual void foo() { cout << "B foo()" << endl; }
protected:
A mInstanceOfA; // don't forget about me!
};
A foo(A& input) {
input.foo();
return input;
}
int main() {
B myB;
B myOtherB;
A myA;
myOtherB = myB;
myA = foo(myOtherB);
}
At the last line myA = foo(myOtherB);, the function will return type an object of type B
Not true. Your function returns an object of type A by value. That means, any value you feed this object to be constructed with will be used to construct a new object of that exact type. So in other words:
int foo(float a) {
return a + 0.5;
}
int u;
u = foo(9.3);
// u has a value of 10
Don't expect u to hold a value that a int cannot.
Same thing if you use user defined types:
A foo(A& input) {
input.foo();
return input; // this expression returns a new A
// using the value of `input`
}
A myA;
myA = foo(myOtherB);
// why would `myA` be anything else than the value of an A?
So then, what happen here?
B foo()
A copy ctor //what calls this?
A op=
A foo(A& input) {
input.foo(); // prints B foo, virtual call. a reference to A that
// points to an object of subclass type B
return input; // copy `input` into the return value object
}
Then, the operator= gets called.
See cppreference
Specifically:
The copy constructor is called whenever an object is initialized (by direct-initialization or copy-initialization) from another object of the same type (unless overload resolution selects a better match or the call is elided), which includes
initialization: T a = b; or T a(b);, where b is of type T;
function argument passing: f(a);, where a is of type T and f is void f(T t);
function return: return a; inside a function such as T f(), where a is of type T, which has no move constructor.
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.
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.