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.
Related
I want to make an operator= and copy constructor, to be called in the inherited class.
For normal objects, it works fine, but when I'm trying to call, for example, operator= with a pointer, it is just copying the object address.
So my question is, how can I call those methods with pointers?
#include <iostream>
// base class
class a {
public:
//constructors
a(): x(0), y(1), z(0){ std::cout << "no parameter constructor A\n"; }
a(int a, int b, int c) :x(a), y(b), z(c){ std::cout << "parameter constructor A\n"; }
a(const a& ob):x(ob.x), y(ob.y), z(ob.z)
{
std::cout << "copy constructor A\n";
}
//operator
a& operator=(const a& obj)
{
if (this != &obj)
{
x = obj.x;
y = obj.y;
z = obj.z;
}
std::cout << "operator = A\n";
return *this;
}
protected:
int x, y, z;
};
//child class
class b : public a
{
public:
//constructors
b() : p(0){ std::cout << "no parameter constructor B\n"; }
b(int X, int Y, int Z, int B) : a(X, Y, Z), p(B) { std::cout << "parameter constructor B\n"; }
b(const b& obj) :p(obj.p), a(obj)
{
std::cout << "copy constructor B\n";
}
//operator =
b& operator=(const b &obj)
{
if (this != &obj)
{
p = obj.p;
&a::operator=(obj);
}
std::cout << "operator = B\n";
return *this;
}
private:
int p;
};
int main()
{
b obj0(4, 8, 16, 32);
b obj1(obj0); // copy constructor
b obj2;
obj2 = obj1; // operator =
std::cout << std::endl << std::endl;
std::cout << "for pointers:\n\n";
a* obj3 = new b(4, 8, 16, 32);
a* obj4(obj3);
obj4 = obj3;
return 0;
}
One of the purposes of using pointers (or references) is to avoid needing to create a copy of the object. Passing a pointer to the object allows the receiver to refer to and manipulate on the original object.
If you wish the pointer to receive a new object, then you would use new.
When dealing with polymorphism as in your example, you would probably need a virtual method that creates a proper clone (sometimes called a deep copy).
class a {
//...
virtual a * clone () const = 0;
};
class b : public a {
//...
b * clone () const {
return new b(*this);
}
};
//...
a *obj4 = obj3->clone();
//...
We leverage that b * is a covariant return type for a *, so that b::clone() can return a b *, but a::clone() can use the b::clone() as an override and still return an a *.
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()
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.
Can someone please explain why i->value() and (i + 1)->value() prints 1 and 3 not 1 and 4 like x[0]->value() << x[1]->value()
#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); //a.m_n=1
const B b(3); //b.m_n=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;
return 0;
}
Thank you
y.push_back(b); creates an instance of A which is a copy of the A subobject in b, and pushes that onto the vector. There are no instances of B on the vector, nor could there be, so B::value() is not called. Read about object slicing
void push_back (const value_type& val);
will create an A copy of val if the vector is defined as std::vector<A> V.
You see here so called slicing problem.
This is why you should use
std::vector<A*> V
or
std::vector<shared_ptr<A> > V