Initialize a object with a derived class constructor - c++

Consider the following C++ code:
#include <iostream>
using std::cout;
class A
{
public:
int a;
A():a(0)
{
cout << "A constructor\n";
}
virtual void f()
{
cout << "f inside A\n";
}
};
class C : public A
{
public:
int c;
virtual void f()
{
cout << "f inside C\n";
}
C():c(0)
{
cout << "C constructor\n";
}
};
int main()
{
A varA = C();
cout << "Size of C class: " << sizeof(C) << "\n";
cout << "Size of varA object: " << sizeof(varA) << "\n";
C* varC = static_cast<C*>(&varA);
varC->f();
cout << "varC->a is " << varC->a << "\n";
cout << "varC->c is " << varC->c << "\n";
}
The output of this program is:
A constructor
C constructor
Size of C class: 16
Size of varA object: 8
f inside A
varC->a is 0
varC->c is 1726166356
I initialize the varA object with the constructor of class C. Constructors of A and C class are called, but the varA is a simply a A object. I cast the address of varA to C* type and I try to call its f() function, but it prints the f() function of class A, so I deduce that it is use the early binding mechanism to call it.
I think if I call the constructor of derived class, like this case, I obtain the same object if I had called the base constructor.
I think the only difference is the other constructors are called. Is my supposition right or there are any other differences?

Classic example of slicing. A varA = C(); leaves you with object of static and dynamic type of A. As a result, C* varC = static_cast<C*>(&varA); exhibits undefined behavior.

You can store a complete derived class in a base-class pointer, however:
int main() {
A* varA = new C();
C* varC = static_cast<C*>(varA);
varC->f();
cout << "varC->a is " << varC->a << endl;
cout << "varC->b is " << varC->b << endl;
cout << "varC->c is " << varC->c << endl;
} // oops, forgot to delete varA/varC, memory leak!

Related

why is destructor called earlier?

I wrote this code to learn the shared_ptr object creation inside my own class.
Why is A object shared_ptr destroyed even before A's print (obj->print() inside B's print) is called?
#include <iostream>
#include <memory>
using namespace std;
class A {
private: string str;
public:
A(string s){
str = s;
cout<<"class A: "<< str << endl;}
~A() { cout << "destroying A: " << str << endl;}
void print() { cout << "A print called" << endl;}
};
class B {
private: shared_ptr<A> obj;
public:
B() { cout << "default construct called" << endl;}
B(string s) {
cout << "shared_ptr creation" <<endl;
shared_ptr<A> obj = make_shared<A>(s);
cout << "shared_ptr creation done" <<endl;
}
~B() { cout<<"destroying B" << endl;}
void print() { obj->print();cout << "B print called" << endl;}
};
void func( B i) { i.print();}
int main()
{
{
B b("hello world");
func(b);
}
cout << "in main" << endl;
return 0;
}
output:
shared_ptr creation
class A: hello world
shared_ptr creation done
destroying A: hello world
A print called
B print called
destroying B
destroying B
in main
In B::B(string), shared_ptr<A> obj = make_shared<A>(s); is constructing a local object which gets destroyed immediately when the constructor ends; it has nothing to do with the data member obj, which points to nothing as the result.
I think you want:
B(string s) {
cout << "shared_ptr creation" <<endl;
obj = make_shared<A>(s); // assignment to the data member obj
cout << "shared_ptr creation done" <<endl;
}
Or initialize it in member initializer list.
B(string s) : obj(make_shared<A>(s)) { // initialize the data member obj
cout << "shared_ptr creation done" <<endl;
}

c++ Make pointer point to another inside a function

I'm working on something which lead me to a situation similar to the example below. I want b to point to a after on test(). Is it possible to this or creating a copy is the only solution?
Thanks.
void test(Object* a, Object* b)
{
std::cout << "test a: " << a << std::endl;
std::cout << "test b: " << b << std::endl;
b = a;
std::cout << "test b assigned: " << b << std::endl;
}
int main()
{
Object* a = new Object();
Object* b = nullptr;
test(a, b);
std::cout << "a: " << a << std::endl;
std::cout << "b: " << b << std::endl;
delete a;
delete b;
}
test a: 0x1aa8930
test b: 0
test b assigned: 0x1aa8930
a: 0x1aa8930
b: 0
In order to modify a pointer, you need to either:
Pass a pointer to your pointer
void test(Object **a, Object **b)
test(&a,&b);
After which you need to dereference that if you want to change the pointer.
Pass a reference to your pointer
void test(Object *&a, Object *&b)
test(a,b);
Here you won't have to dereference anything if you want to change the address.
For a, you don't necessarily have to pass a pointer to pointer or a reference to pointer (unless you plan to modify it too in the future), but for b you have to in order to modify it.
P.S. change your void main() to int main()
You can do like this:
void test(Object* a, Object*& b)
{
std::cout << "test a: " << a << std::endl;
std::cout << "test b: " << b << std::endl;
b = a;
std::cout << "test b assigned: " << b << std::endl;
}
int main()
{
Object* a = new Object();
Object* b = NULL;
test(a, b);
std::cout << "a: " << a << std::endl;
std::cout << "b: " << b << std::endl;
delete a, b;
}
Output will be:
test a: 0x7a0d28
test b: 0
test b assigned: 0x7a0d28
a: 0x7a0d28
b: 0x7a0d28
Its because in question, you have passed the value of b, not a reference to it, which is required to modify it. Variables can only be modified by a function if that function receives the address of those variables, and that can only can be done via either a pointer (Object**) or a reference (Object* &)
Nowadays we have something called shared_ptr, which does exacly what you want. Plus you don't have to clean it up after you're finished with it!
Example:
#include <memory>
#include <iostream>
using Object = int;
void test(const std::shared_ptr<Object>& a, std::shared_ptr<Object>& b)
{
b = a;
std::cout << "test b assigned: " << b.get() << "\n";
}
int main()
{
auto a = std::make_shared<Object>();
std::shared_ptr<Object> b;
std::cout << "test a: " << a.get() << "\n";
std::cout << "test b: " << b.get() << "\n";
test(a, b);
std::cout << "test a: " << a.get() << "\n";
std::cout << "test b: " << b.get() << "\n";
return 0;
}
output (g++ 5.4.0):
test a: 0x21e2c30
test b: 0
test b assigned: 0x21e2c30
test a: 0x21e2c30
test b: 0x21e2c30
live demo

Neither Default Constructor nor Copy Constructor is called when using anonymous object

Below is the snippet aimed to test the constructors. It was run in VS 2015.
In my opinion, "B b(B())" has the same function as "B b = B()", however, my code seems to say that they behave different.
I know there's copy elision by compiler optimization, but I think the default constructor should be called at least when execute "B b(B())".
Can anyone help point out where my misunderstood is?
class B
{
public:
B() {
++i;
x = new int[100];
cout << "default constructor!"<<" "<<i << endl;
cout << "x address:" << x << endl << "--------" << endl;
}
B(const B &b) //copy constructor
{
++i;
cout << "Copy constructor & called " << i<< endl
<< "--------" << endl;
}
B(B &&b)//move constructor
{
x = b.x;
++i;
b.x = nullptr;
cout << "Copy constructor && called" << i << endl
<<"x address:"<< x << endl << "--------" << endl;
}
void print()
{
cout << "b address:" << x << endl << "--------" << endl;
}
private:
static int i;
int *x;
};
int B::i = 0;
int main()
{
B b1; //default constructor
b1.print();
B b2 = B(); //default constructor only
b2.print();
B b3(B()); //????nothing called... why???
B b4 = b2; //copy constructor
B b5 = move(b2); //move constructor
b2.print();
return 0;
}
Note that B b(B()) is a function declaration, not a variable definition at all, then no constructor would be called.
According to Most vexing parse, B b(B()) is a function declaration, for a function named b which returns an object of type B and has a single (unnamed) parameter which is a pointer to function returning type B and taking no parameter.
You can solve it by using braces (list initlization (since C++11)), like
B b1( B{} );
B b2{ B() };
B b3{ B{} }; // preferable from C++11

Explicity pass base type

I have an explicit function that takes a reference to the base type of a class. What is the proper way to pass that in?
I am currently doing a static cast:
#include <iostream>
using namespace std;
struct Base
{
Base() { cout << "Base Constructor" << endl; }
Base(Base const& c) { cout << "Base-Base Constructor" << endl; }
};
struct Derived : public Base
{
Derived() { cout << "Derived Constructor" << endl; }
explicit Derived(Base const& c) { cout << "Derived-Base Constructor" << endl; }
Derived(Derived const& c) { cout << "Derived-Derived Constructor" << endl; }
};
int main()
{
Base B;
cout << "\n";
Derived D;
cout << "\n";
Base* test1 = new Derived(D);
cout << "\n";
Base* test3 = new Derived(static_cast<Base>(D));
cout << "\n";
Base* test2 = new Derived(B);
cout << "\n";
return 0;
}
but that calls the copy constructor of the base class.
I could pass *static_cast<Base*>(&D), but that seems a bit hackish. I feel like I am just overlooking a simple way to do this. Thanks.
Use this:
static_cast<Base&>(D)
Or this:
static_cast<const Base&>(D)

How does RAII work when mixing default and non-default constructors

I want to write a library wrapper class (LibWrap) around a C library that uses malloc/free. To do this I want to use C++'s RAII to allocate and free memory. I used lib_address as a random example address that I would receive from the library. However when defining my memeber variable the destructor that is called somehow has this lib_address.
I would expect the destructor of the member variable created by the default constructor not to know the new address that I am putting into the constructor of my replacement member variable.
#include <stdlib.h>
#include <iostream>
using namespace std;
class LibWrap
{
int j;
int lib_address;
public:
LibWrap(): //default LibWrap
j(0),
lib_address(0)
{
cout << "default LibWrap "<<j <<"\t\t"<<lib_address << "\t" << this<<endl;
}
LibWrap(int f_j): //special LibWrap
j(0),
lib_address(0)
{
j = f_j;
lib_address = rand();
cout << "special LibWrap " << j<<"\t"<< lib_address<< "\t" << this <<endl;
}
~LibWrap()
{
cout << "killing LibWrap " << j<<"\t" <<lib_address <<"\t" << this<< endl;
}
int g()
{
return j;
}
};
class A
{
int i;
LibWrap b;
public:
A(): //default A
i(0)
{
cout << "default A\t"<<i << endl;
}
A(int f_i)://special A
i(0)
{
i = f_i;
cout << "special A\t"<<i << endl;
b = LibWrap(10);
}
~A()
{
cout << "killing A\t"<<i << endl;
}
void p()
{
cout <<"Test values: "<< i<< "," << b.g() << endl;
}
};
int f()
{
//A a; a.p();
cout << "variable\t\tlib_address\treal_address" << endl;
A a = A(1);
cout << "End" << endl;
//a.p();
}
int main()
{
f();
}
Running this code I would expect to get the following result:
variable lib_address real_address
default LibWrap 0 0 0xbfef2e28
special A 1
special LibWrap 10 1804289383 0xbfef2df8
killing LibWrap 10 1804289383 0xbfef2df8 --would expect kiling LibWrap 0 0 0xbfef2e28
End
killing A 1
killing LibWrap 10 1804289383 0xbfef2e28 --would expect killing LibWrap 10 1804289383 0xbfef2df8
b = LibWrap(10);
This does not initialize b. b has already been initialized as part of constructing A. What you're doing is creating a temporary LibWrap and copying that temporary into b. Then, you're destroying that temporary LibWrap (which is where the extra destructor call with the lib_address comes from).
The temporary LibWrap is where the "0xbfef2df8" address comes from. The b variable is the "0xbfef2e28" address. That's why you're getting them in that order.