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
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;
}
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
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
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)
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.