Initializing derived classes through bases - c++

Consider:
struct V {
V(int i) {
std::cout << "initialized v" << '\n';
}
};
struct A {
A() {
std::cout << "initialized a" << '\n';
}
};
struct B : virtual V, virtual A {
B(int i) :V{i} {
std::cout << "initialized b" << '\n';
}
};
class C : virtual V, virtual A {
public:
C(int i) : V{i} {
std::cout << "initialized c" << '\n';
}
};
class D : virtual public B, virtual public C {
public:
D(int i, int j) :V{i}, B{i}, C{j} {
std::cout << "initialized d" << '\n';
}
};
If I initialize D in main(), like this:
int main() {
D* d = new D{3,3}; //ok
B* b = new D{3,3}; //ok
C* c = new D{3,3}; //undefined
delete d;
delete b;
delete c;
}
But if I use a factory, like this:
C* factory() {
return new D{3,3};
}
int main() {
factory(); //ok
}
I can't figure out why it's causing undefined behavior when I initialize D through C in main() but works fine when I use other functions. What's wrong with C? Isn't it just the same as B?
Edit: So my code runs fine on this demo as I think it should. If there's nothing wrong with my code, is there a problem with my development environment? I'm using the latest mingw-w64 with eclipse CPP.

You are looking for the undefinedness in all the wrong places.
delete b;
delete c;
Both lines invoke undefined behavior, by deleting a derived class object (a D) through a pointer to base class (a B* or C*) with no virtual destructor. Give them one (e.g., by adding virtual ~V() = default; to V), and the crash should disappear.
This is why it's important to verify that the code you post here in fact reproduces the crash you are seeing when compiled and run. Someone would probably have spotted the problem in less than 5 minutes if the full code were available at the beginning. Instead, we spent 45 minutes trying to reproduce the problem.

Related

Constructor not throwing exception [duplicate]

This question already has an answer here:
C++ constructor not called
(1 answer)
Closed 4 years ago.
In my code below, I wanted to test what would happen if I had an object, that contained another object whose constructor throws exception. But the code below does absolutely nothing. Nothing is printed on the console at all.
class A
{
public:
A()
{
cout << "in A constructor" << endl;
throw "error creating A";
}
~A()
{
cout << "destructing A" << endl;
}
};
class C
{
public:
C()
{
cout <<"in C constructor" << endl;
}
~C()
{
cout << "in C destructor " << endl;
}
};
class B
{
public:
C c;
A a;
B(A a_, C c_): a(a_), c(c_){}
B(){}
};
int main()
{
try{
B b(A, C);
//B b;
}
catch(char const* s)
{
cout <<"catching" << endl;
}
}
If in the try block, I use commented code instead, then it shows fine.
I also tried doing
B b(A(), C());
Still nothing.
This is a function declaration with return type B, name b, and two unnamed arguments of type A and C:
B b(A, C);
The same for
B b(A(), C());
as names can be enclosed by parentheses (to allow grouping, necessary when working with e.g. function pointers etc.), and even names that are left out can be enclosed by parentheses. You can turn it into a variable b of type B by
B b(A{}, C{});
One of the motivation for the curly braces to initialize variables was to disambiguate in such cases. Here, it obviously comes in handy.

Access members of a class within a different class in c++

I am trying to understand object oriented programming using c++. The following is a minimal example for which the result is not what I naively expect:
#include <iostream>
class B {
public:
B (int val) : val(val) {;}
int get_val() { return val; }
int set_val(int a) { val = a; }
private:
int val;
};
class A {
public:
A (B b) : b(b) {;}
B get_b() { return b; }
private:
B b;
};
int main(){
B b_main(5);
std::cout << b_main.get_val() << std::endl; // Prints 5, which makes sense
A a_main(b_main);
std::cout << a_main.get_b().get_val() << std::endl; // Prints 5, which makes sense
a_main.get_b().set_val(2);
std::cout << a_main.get_b().get_val() << std::endl; // Why does this not print 2?
return 0;
}
The last cout statement does not make sense to me. In the second to last line, I set the value of the object to be 2, so why does this not print 2? Looking at some similar questions on Stack Exchange, I found some suggestions to make A and B be friends of each other. I tried adding friend class A in class B and friend class B in class A, but this did not work. In my understanding, adding the friend statements should be unnecessary since I have the get_b() method in class A. I found some suggestions to try passing the object of type B in by reference to the constructor of A: A (B& b) : b(b) {;} but this did not work either.
Can anyone explain to me why the program is not producing the intended result and also how to obtain the desired result (that is, the last cout statement prints 2)?
Note: I also experimented with the following. I made the private variable b of class A be public:
#include <iostream>
class B {
public:
B (int val) : val(val) {;}
int get_val() { return val; }
int set_val(int a) { val = a; }
private:
int val;
};
class A {
public:
A (B b) : b(b) {;}
B b; // This is now public
//B get_b() { return b; } // This is no longer needed
private:
};
int main(){
B bmain(5);
std::cout << bmain.get_val() << std::endl;
A amain(bmain);
std::cout << amain.b.get_val() << std::endl;
amain.b.set_val(2);
std::cout << amain.b.get_val() << std::endl; // Works!
return 0;
}
And now I obtain the desired result. Is this how the code should be implemented as opposed to the first code snippet? I would like to have a get_b() method as in the first code snippet, but if this is not the correct way of going about this, please let me know.
In the second to last line, I set the value of the object to be 2, so why does this not print 2?
Because you return a copy of the B object in a_main with the get_b() method. What happens is that the b variable in a_main is copied, i.e. another object of class B, identical to the b member, is created, and returned to the caller. Then, that new B object is modified. But it has no connection to the original b in a_main. This has little to do with visibility and member access.
However, in the second example, you expose the b member in a_main and directly operate on that object without making a copy of it, thus the successful result. What the public modifier changes is that it allows you to access the b object directly, hence the effect.
I found some suggestions to try passing the object of type B in by reference to the constructor of A: A (B& b) : b(b) {;} but this did not work either.
That isn't going to work. What happens when you do so, is that the A::b is initialized using the value that is passed by reference, true. But the reference only leads to no additional copy of b passed to the constructor being made. This reference does not create a link between the b passed to the constructor and A::b. It's on the other end, so to say.
By the way, A (B& b) : b(b) {;} that the c'tor parameter name is identical to the member name is a bad practice. It's a good idea to have them named similarly, but still, add e.g. an underscore: A (B& _b) : b(_b) {;}
If you want to achieve the same result in the first snippet, return a reference to b like so:
B& get_b() { return b; }
Still, this is undesirable, because you expose a private member of class A just to allow clients of A to modify a certain property of that member. Better provide a method in A to set the val property of A::b without giving full access to A::b.
Definitely see this: What's the difference between passing by reference vs. passing by value?
and maybe this: Java and C++ pass by value and pass by reference
because I have a feel that you're coming from Java and expect pass-by-reference in C++ by default.
get_b returns a copy of your private variable b, not the actual variable. If you want to be able to access it, you need to return a reference to b so that the returned value can be manipulated. Your get_b definition should look like this:
B& get_b() { return b; }
if that is what you expect to do. However, this is not usually a desirable solution. If you are going to be actively changing the value of b you should write a set_b function to manipulate the variable. And if you are really working with the variable a lot, reading and writing values to it, you should keep it public for fast access.
Just for the sake of completeness, you can solve this problem as a C programing problem rather than using all the fancy references in C++ programing. When you get b_main from a_main, the returned object does not occupy the same memory address.
#include <iostream>
class B {
public:
B (int val) : val(val) {;}
int get_val() { return val; }
int set_val(int a) { val = a; }
private:
int val;
};
class A {
public:
A (B b) : b(b) {;}
B get_b() { return b; }
private:
B b;
};
int main(){
B b_main(5);
B* addrb = &b_main;
std::cout << b_main.get_val() << std::endl; // Prints 5, which makes sense
std::cout<<"Address of b_main: "<<addrb<<std::endl;
A a_main(b_main);
B bt = a_main.get_b();
addrb = &(bt);
std::cout << a_main.get_b().get_val() << std::endl; // Prints 5, which makes sense
std::cout<<"Address of a_main.get_b(): "<<addrb<<std::endl;
a_main.get_b().set_val(2);
std::cout << a_main.get_b().get_val() << std::endl; // Why does this not print 2?
return 0;
}
Notice the difference in address of the new cout statements. One way to fix this is to return pointers rather than b itself. i.e.
#include <iostream>
class B {
public:
B (int val) : val(val) {;}
int get_val() { return val; }
int set_val(int a) { val = a; }
private:
int val;
};
class A {
public:
A (B b) : b(b) {;}
B* get_b() { return &b; }
private:
B b;
};
int main(){
B b_main(5);
//B* addrb = &b_main;
std::cout << b_main.get_val() << std::endl; // Prints 5, which makes sense
//std::cout<<"Address of b_main: "<<addrb<<std::endl;
A a_main(b_main);
//B bt = a_main.get_b();
//addrb = &(bt);
std::cout << a_main.get_b()->get_val() << std::endl; // Prints 5, which makes sense
//std::cout<<"Address of a_main.get_b(): "<<addrb<<std::endl;
a_main.get_b()->set_val(2);
std::cout << a_main.get_b()->get_val() << std::endl; // Why does this not print 2?
return 0;
}

Is it possible to access virtual methods of different ancestors of a polymorphic class through a single pointer?

I am building an interface, where it would be a little bit inconvenient to use separate variables to access individual interfaces, it would be great if somehow I could create a union of the two.
In a file:
struct A{
virtual int auu() { return 41; }
};
struct B{
virtual int boo() { return 43; }
};
In another file:
#include <path to A, B>
struct C : public A, public B{
int auu() { return 20; }
int boo() { return 22; }
};
And another file:
#include <declaration of A and B, but not C>
void doSth(A* a)
{
B * b = dynamic_cast<B*>(a);
/* I can only call auu with a */
a->auu();
/* I can only call boo with b */
b->boo;
/* Something like this would be ideal: */
<??? type> * C_interface = dynamic_interface_cast<B*>(a)
C_interface->auu();
C_interface->boo();
}
So is there to call both auu and boo through only one pointer variable and without the knowledge of C's implementation (not casting it to )? Also I'd like to avoid creating inheritance hierarchy that is NOT in connection with class C.
Probably the answer is no, however I'm curious if an idea like this has come up from the side of the language developers because to my primitive mind it's not a so far fetched idea.
EDIT:
In real, A and B are abstract. A is a Simulation object that has methods like size() and length(). B is an IO interface, implementing getters and setters, but it doesn't know about sizes so I have to use both interfaces in many calculations. C is a specialized Simulation that implements the former 2.
EDIT:
I rewrote the question, maybe it actually makes sense now.
I'll ilustrate the point I made in my comment. It's perfectly legal to cast between siblings, as long as the actual object is derived from both.
#include<iostream>
using namespace std;
struct A{
virtual int auu() { return 41; }
};
struct B{
virtual int boo() { return 43; }
};
struct C : public A, public B{
int auu() { return 20; }
int boo() { return 22; }
};
void take_B(B* bp)
{
cout << bp->boo() << endl; // expected
cout << "(The base class would say "
<< bp->B::boo() << ")" << endl; // base class implementation
A *ap = dynamic_cast<A*>(bp);
if(!ap)
{
cerr << "weird, this cast should be possible!" << endl;
}
else
{
cout << ap->auu() << endl; // should work
cout << "(The base class would say "
<< ap->A::auu() << ")" << endl; // base class implementation
}
}
int main()
{
C c;
take_B(&c);
cout << endl << "... and again:" << endl;
// just to clarify: The actual pointer type is irrelevant.
B *bp = &c;
take_B(bp);
return 0;
}

CRTP / Macros / Avoid casting pointer of derived class

Lately I've been working in some project and the thing is that we've encountered a situation in which we need to be able to do stuff like this.
#define TYPED(Type) \
virtual Type *typedThis() const { return (Type*) this; }
class A {
public:
TYPED(A)
virtual void describe() { std::cout << "I am type A\n"; }
static int x;
};
int A::x = 1;
class B : public A {
public:
TYPED(B)
virtual void describe() { std::cout << "I am type B\n"; }
static int x;
};
int B::x = 2;
int
main(int argc, char** argv)
{
B* b = new B();
A* b2 = b;
b->describe();
b2->describe();
std::cout << b->typedThis()->x << std::endl;
std::cout << b2->typedThis()->x << std::endl; // AQUI DEBERIA DAR 2 !! :c
}
This is of course just a toy example. The basic idea of what we would like to do is to define a function typedThis() who does the casting of the pointer into the correct type and then access to the correct variable x, and printing out 2 instead of 1.
However, the output is the following:
I am type B
I am type B
2
1 //Here should also be 2
What I find really interesting is that the virtual method describe() seems to be working the way we want. Therefore, I could infer that the method typedThis() is also working the way we would like to. But if so, why does C++ see this pointer as an A* instead of an B*. If C++ saw this pointer like a B* then it would have used the correct variable x. Can someone explain this to me?
I tried using CRTP, however I don't feel like this would make things easier, because in the project we will be using a lot (A LOT) of different classes who derive between them constantly, I saw some articles of how to use CRTP when having multiple inheritance, however they are really messy and hard to integrate with what we have so far.
I removed all distractions from the example:
class A {
public:
virtual A *typedThis() const { return (A*) this; }
static int x = 1;
};
class B : public A {
public:
virtual B *typedThis() const { return (B*) this; }
static int x = 2;
};
int main()
{
B* b1 = new B;
A* b2 = b1;
std::cout << b1->typedThis()->x << "\n";
std::cout << b2->typedThis()->x << "\n";
}
typedThis doesn't do anything.
b1->typedThis() returns a B* which points to a B.
Likewise, b1 itself is a B* which points to a B.
b2->typedThis() returns an A* which points to a B.
Likewise, b2 itself is an A* which points to a B.
So b1->typedThis() is the same as b1 and b2->typedThis() is the same as b2, and the last two lines of the example are equivalent to the following:
std::cout << b1->x << "\n";
std::cout << b2->x << "\n";
Also take note that your C-style casts discard the const qualifiers of the objects.

C++ const reference member extending lifetime of object

This is related to a question posted yesterday.
class A
{
public:
mutable int x;
A()
{
static int i = 0;
x = i;
i++;
std::cout << " A()" << std::endl;
}
~A()
{
std::cout << "~A()" << std::endl;
}
void foo() const
{
x = 1;
};
};
class B
{
public:
const A & a;
B(const A & a) : a(a)
{
std::cout << " B()" << std::endl;
}
~B()
{
std::cout << "~B()" << std::endl;
}
void doSomething()
{
a.foo();
};
};
int main()
{
B b((A()));
b.doSomething();
}
Now, a's destructor is called before the call to doSomething. However, the call works although the function basically changes a member of A. Is it not the same instance. No other A's are created. I used the static inside A's constructor to keep track of that. Can anyone explain?
This is undefined behavior, so there is no language standard explanation.
However, the destructor of A doesn't do anything to the memory area where x is stored, so if you look there later the value might just still be there. Or if you try to write to the address, the address is still there. You are just not allowed to do that.
Bo is correct.
In addition, you could check the address where 'A' is stored, and that should confirm that that address simply hasn't been reused yet (keep in mind a destructor frees ("releases") the memory, but doesn't traverse the data structure setting all of the bits back to 0; that would be inefficient).
If, for example, you find that A is stored on top of the stack, then you are simply fortunate that your subsequent function call doesn't pass in a parameter, as that would overwrite A's memory region.
Your reference is invalid after ~A() and it is undefined behavior
~A() calls destructors of all members of A in addition
Try so for example
class B
{
public:
const std::string & a;
B(const std::string & a) : a(a)
{
std::cout << " B()" << std::endl;
}
~B()
{
std::cout << "~B()" << std::endl;
}
void doSomething()
{
std::cout << "a = " << a << std::endl;
};
};
int main()
{
B b(std::string("I love C++ so much!"));
b.doSomething();
}
Expanding on Bo's answer.
For a temporary to exist, space will be reserved on the stack. This space is actually reserved as long as the semantics require the temporary to exist, and may then be reuse for something else.
If you were trying to use the memory after it has been reused, you would observe a strange behavior (the very definition of undefined behavior being that anything can happen). As it is, you luck out and the memory is still there, in the state you expect it to.
Example:
#include <iostream>
struct A {
A(): p(0) {}
~A() { if (p) { std::cout << *p << "\n"; } }
int* p;
};
int bar0();
void bar1(int i);
int main() {
A a;
{
int x = 4; a.p = &x;
}
{
int y = bar0(); bar1(y);
}
}
int bar0() { return 7; }
void bar1(int i) { std::cout << i << "\n"; }
Here, the compiler may choose to reuse the space of x for y, or just do anything it wants, and thus you're actually printing garbage.
Here is gcc 4.3.4 (and 4.5.1) output (courtesy of ideone):
7
4
Meaning that the space is not reused with those...