Joran Bigalet
Joran Bigalet

Reputation: 3

Inheritance and cast

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

Answers (4)

quamrana
quamrana

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

Lol4t0
Lol4t0

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:

  1. 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));
    
  2. replace pointers with references. Then you can use value semantics.

Upvotes: 3

Wug
Wug

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

Maksim Skurydzin
Maksim Skurydzin

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

Related Questions