Reputation: 3
I'm having some trouble with the class casting in C++.
To learn, I wanted to create a class which just make operations, like sums, but it seems to crash everytime I launch it.
Here is my simple classes:
#include <iostream>
class CCalculation {
public:
CCalculation() {};
virtual int calculate() = 0;
};
class CCalc_CONST : public CCalculation {
int x;
public:
CCalc_CONST(int a) : x(a) {};
int calculate() { return x; };
};
class CCalc_ADD : public CCalculation {
CCalculation *x;
CCalculation *y;
public:
CCalc_ADD(CCalculation *a, CCalculation *b) {
this->x = a;
this->y = b;
};
int calculate() {
std::cout << "Calculation...\n";
return x->calculate() + y->calculate();
};
};
And my test:
CCalculation *a = &CCalc_CONST(4);
CCalculation *b = &CCalc_CONST(1);
CCalculation *c = &CCalc_ADD(a,b);
std::cout << "res: " << c->calculate() << "\n";
It seems to crash everytime (I got no compiler error or warning). The only way to run it I found is when I'm printing a->calculate and b->calculate at the CCalc_ADD construction. I have absolutely no clue why i need to call the calculate function to make it work.
Can someone please explains to me how to actually do it ?
Upvotes: 0
Views: 152
Reputation: 39414
To get a working program you don't even need to use new
:
CCalc_CONST a(4);
CCalc_CONST b(1);
CCalc_ADD c(&a,&b);
std::cout << "res: " << c.calculate() << "\n";
Upvotes: 2
Reputation: 12557
First of all, you should turn on all warnings (see docs to your compiler, in gcc
-Wall
)
Then you will see, that your compiler will blame you:
1.cpp: In function 'int main()':
1.cpp:56:37: error: taking address of temporary [-fpermissive]
1.cpp:57:37: error: taking address of temporary [-fpermissive]
1.cpp:58:37: error: taking address of temporary [-fpermissive]
Actually, here
CCalculation *a = &CCalc_CONST(4);
you just create temporary object that will be destroyed imminently after creation and you get broken pointer.
You have 2 alternatives:
create objects in dynamic memory (but in this case I will recommend make complex calculation owner of simpler)
class CCalc_ADD : public CCalculation {
std::unique_ptr<CCalculation> x;
std::unique_ptr<CCalculation> y;
public:
CCalc_ADD(CCalculation *a, CCalculation *b):x(a), y(b)
{
};
int calculate() {
std::cout << "Calculation...\n";
return x->calculate() + y->calculate();
};
};
std::unique_ptr<CCalculation> a(new CCalc_CONST(4));
//...
CCalc_ADD c (std::move(a), std::move(b));
replace pointers with references. Then you can use value semantics.
Upvotes: 3
Reputation: 13196
You're not using new. Test like this:
CCalculation *a = new CCalc_CONST(4);
CCalculation *b = new CCalc_CONST(1);
CCalculation *c = new CCalc_ADD(a,b);
You can weed out things like address-of on temporaries by compiling with -Wall
, which enables all compiler warnings. The compiler is your friend and is there to help. Love the compiler.
Upvotes: 0
Reputation: 10541
You are trying to access temporary objects that are no longer alive. Use operator new
for allocating memory for an object and calling its constructor.
CCalculation *a = new CCalc_CONST(4);
CCalculation *b = new CCalc_CONST(1);
CCalculation *c = new CCalc_ADD(a,b);
I have tried it with GCC and it issues a very clear warning about this:
test.cpp: In function ‘int main()’:
test.cpp:35:33: error: taking address of temporary [-fpermissive]
test.cpp:36:37: error: taking address of temporary [-fpermissive]
test.cpp:37:37: error: taking address of temporary [-fpermissive]
Upvotes: 0