Consider the following piece of code:
struct A {
int a;
A(int a): a(a) {}
char *get_data() { return reinterpret_cast<char*>(this); }
};
struct B: public A {
int b[100];
B() : A(0) {}
};
Is it safe to do the following?
B b;
Write(/* key= */ 1, b.get_data());
A *a = reinterpret_cast<A *>(Read(1));
// Some code here.
B *b = reinterpret_cast<B *>(a->get_data());
Related
I have a basic question with the flow of constructors w.r.t. inheritance in C++.
The classes are defined as follows:
Base class A is defined as follows. It has 2 constructors - A() and A(int x). A(int x) calls A().
class A {
protected:
int a;
public:
A() {
a = 0;
}
A(int x) {
A();
a = x;
}
};
Derived class B is derived from Base class A. It has 2 constructors - B() and B(int x, int y).
B() calls A() in addition to setting member variable b to 0.
B(int x, int y) calls A(x)
class B : public A {
protected:
int b;
public:
B() : A() {
b = 0;
}
B(int x, int y) : A(x) {
B();
b = y;
}
void print() {
std::cout << "a=" << a << ",b=" << b << std::endl;
}
};
int main() {
B b(1, 2);
b.print();
}
Output:
a=1,b=2
Expected:
a=0,b=2
I am expecting the flow as below,
B b(1, 2) ->
B(int x=1, int y=2) ->
A(int x=1) ->
A() sets a=0 ->
A(int x=1) sets a = 1 ->
B() ->
A() overwrites a=0 -> <===== Shouldn't a=0 get reflected in final output ?
B() sets b = 0 ->
B(int x=1, int y=2) sets b = 2
However, I am seeing a=1 and b=2.
Does anyone know what is that I am missing in this code flow?
#EDIT:#
Perhaps the better way to do this is as #Jarod42 suggested. The code is updated below. It is still unclear how come the above code is able to get a=1 and b=2. Dry runs indicate that we should be getting a=0 and b=2.
class A {
protected:
int a;
public:
A() : A(0) {
}
A(int x) {
a = x;
}
};
class B : public A {
protected:
int b;
public:
B() : B(0, 0) {
}
B(int x, int y) : A(x) {
b = y;
}
void print() {
std::cout << "a=" << a << ",b=" << b << std::endl;
}
};
Instead of
A(int x) {
A(); ...
you have to delegate to the other constructor with :
A(int x) : A() {
...
Same within class B. Hope this solves your question.
#include<iostream>
class A {
int a, b;
public:
void setdata(int x, int y) { a = x; b = y; }
void showdata() { std::cout << a << b; }
};
class B : public A { };
int main() {
A a1;
B b1;
a1.setdata(5, 4);
a1.showdata();
b1.showdata();
}
I just want to print the values of the a and b members using the b1 object of class B, as it can access the member functions of class A since class B has public inheritance of class A. But, I am getting garbage values when I try to print the values of a and b using b1.
Can someone explain why this is happening and how to fix it?
a1 and b1 are completely separate object instances in memory. They have their own copies of the a and b members in memory. They have nothing to do with each other at all. Whatever you do to a1 does not affect b1 at all, and vice versa.
You are initializing the members of a1 only, you are not initializing the members of b1 at all. That is why you are seeing garbage when you try to print out the members of b1.
Before calling b1.showdata(), you need to call b1.setdata() to initialize b1's members, eg:
int main() {
A a1;
B b1;
a1.setdata(5, 4);
a1.showdata();
b1.setdata(1, 2); // <-- add this!
b1.showdata();
}
You should also give class A a default constructor that initializes the members to default values, in case setdata() is not called after construction (such as what happened in your case), eg:
class A {
int a, b;
public:
A() : a(0), b(0) {} // <-- add this!
void setdata(int x, int y) { a = x; b = y; }
void showdata() { std::cout << a << b; }
};
Alternatively, you might consider giving class A and class B a constructor that takes values as input, eg:
class A {
int a, b;
public:
A() : a(0), b(0) {}
A(int x, int y) : a(x), b(y) {} // <-- add this!
void setdata(int x, int y) { a = x; b = y; }
void showdata() { std::cout << a << b; }
};
class B : public A {
public:
B() : A() {}
B(int x, int y) : A(x, y) {}
};
/* or simpler:
class B : public A {
public:
using A::A; // <-- inherit all constructors
};
*/
int main() {
A a1(5, 4);
B b1(1, 2);
a1.showdata();
b1.showdata();
}
My question is very similar like other's, but a bit different. I have a sample code:
class B1 {
private :
int * ptr;
public:
B1() : a{ 1 } { ptr = new int{ 2 }; }
B1(const B1& other) : a{ other.a } { ptr = new int{ *other.ptr }; }
~B1() { delete ptr; }
int a;
virtual void smthing() = 0;
};
class D : B1 {
public:
D(int i) : B1{} {}
D(const D& a) : B1{ a } {}
void smthing() { return; };
};
int main() {
D d { 3 };
D dd { d };
return 0;
}
I am using vs2015, and this code is works, but gives me error: object of abstract class type "B1" is not allowed...
If I remove this line D(const D& a) : B1{ a } {}, the base class copy constructor is called and there's no problem, but if I need the derived class copy constructor how can I make this work without error?
Thanks for the answer!
I have this class
struct B {
B( int x=0 ) { }
virtual void something() {
std::cout << "B()";
}
};
struct A {
B b;
int a;
A( int a, int b_ ) : a(a), b(b_) {a}
};
I have implemented another class C
struct C : public B {
C( int x ) : B(b) { }
virtual void something() {
std::cout << "C()";
}
};
What is the best way to get A use C instead of B ?
I already tried this :
struct A {
B & b;
int a;
A( int a, B &b_ ) : a(a), b(b_) {a}
};
But then I have to use std::map<int, A>
which is giving compilation errors:
'A::A' : no appropriate default constructor available.
so i did this :
struct A {
B & b;
int a;
A( int a=0, B &b_=B() ) : a(a), b(b_) {a}
};
in my main
std::map<int,A> mmap;
for( int i=0;i<5;++i ) {
auto & b = C();
mmap.insert( std::make_pair(i,A(i,b) ) ) ;
}
but these C's object in mmap's A become B as soon as auto & b goes out of scope.
Its not working. How to fix it ?
In the A constructor, you try to assign a temporary instance of B to reference to B, which is illegal.
What you have to do is to change this reference by a pointer to this class :
#include <iostream>
#include <memory>
#include <map>
using namespace std;
struct B {
B( int x=0 ) { }
virtual void something()
{
std::cout << "B()";
}
};
struct A {
shared_ptr<B> b;
int a;
A( int a = 0, shared_ptr<B> b = shared_ptr<B>(new B()) ) : a(a), b(b) {}
};
struct C : public B {
C( int x ) { }
virtual void something()
{
std::cout << "C()";
}
};
int main()
{
shared_ptr<B> b = shared_ptr<B>( new C(0));
// Polymorphic test
b->something();
A a (0, b);
// map test
map<int, A> my_map;
my_map[0] = a;
return 0;
};
If you can not use C++11, just change smart pointers by naked pointers and handle the dynamic memory properly as usual. Or even better : use the Boost library, as mentioned by chris.
Hi I have a question about the constructor initialization order. Given below
struct B {}
struct A
{
B& b;
A(B& b) : b(b) {}
}
struct C
{
B b;
A a;
C() : b(),a(b) {}
}
struct D
{
A a;
B b;
D() : a(b),b() {}
}
I know that C is valid as b gets initialized before a. But what about D? b wouldn't have been constructed yet, but the address should already be known, so it should be safe?
Thanks
They're both valid because A doesn't call into B at all. If A accessed a data member or member function of B, then that would be invalid. In the existing case of A, it's impossible to produce an invalid example.
just a sample to show you when stuff happens
struct B {
B() {
print("struct B / constructor B", 1);
}
};
struct A
{
B& b;
A(B& b) : b(b) {
print("struct A / constructor with B", 1);
};
};
struct C
{
B b;
A a;
C() : b(),a(b) {
print("struct C / constructor C", 1);
};
void dummy()
{
print("dummy",1);
}
};
struct D
{
A a;
B b;
D() : a(b),b() {
print("struct D / constructor D", 1);
};
void dummy()
{
print("dummy",1);
}
};
int main(int argc, char* argv[])
{
D dTest;
dTest.dummy();
C cTest;
cTest.dummy();
}
--- output
struct A / constructor with B
struct B / constructor B
struct D / constructor D
dummy
struct B / constructor B
struct A / constructor with B
struct C / constructor C
dummy