0

I'm trying to make my operator work (and it sometimes did) but on the output I receive a junk.

I've tried implicit type conversion and in IndProd constructor set private methods of object f through setters, nothing helped.

class FoodProd : public Exp
{
    private:
        int consump_term;
        char *producer;
    public:
        FoodProd()
        {
            producer = new char[7];
            strcpy(producer, "NONAME");
            consump_term = 0;
        }
        FoodProd(int term, char *str)
        {
            int size1 = strlen(str) + 1;
            producer = new char[size1];
            if (producer)
                strcpy(producer, str);
            consump_term = term;
        }
        FoodProd(const FoodProd &food)
        {
            producer = new char[strlen(food.producer) + 1];
            strcpy(producer, food.producer);
            consump_term = food.consump_term;
        }
        ~FoodProd()
        {
            if (producer)
                delete[] producer;
        }
...
}

class IndProd : public Exp
{
    private:
        char *category;
        int price;
        char *manufacturer;
    public:
        IndProd()
        {
            category = new char[7];
            strcpy(category, "NONAME");
            manufacturer = new char[7];
            strcpy(manufacturer, "NONAME");
            price = 0;
        }
        IndProd(char *cat, int pr, char *manuf)
        {
            category = new char[strlen(cat) + 1];
            strcpy(category, cat);
            price = pr;
            manufacturer = new char[strlen(manuf) + 1];
            strcpy(manufacturer, manuf);
        }
        IndProd(const IndProd &ind)
        {
            category = new char(strlen(ind.category) + 1);
            strcpy(category, ind.category);
            price = ind.price;
            manufacturer = new char(strlen(ind.manufacturer) + 1);
            strcpy(manufacturer, ind.manufacturer);
        }
        ~IndProd()
        {
            if (category)
                delete[] category;
            if (manufacturer)
                delete[] manufacturer;
        }
        IndProd (FoodProd obj)
        {
            category = new char[7];
            strcpy(category, "NONAME");
            manufacturer = new char[strlen(obj.get_producer()) + 1];
            strcpy(manufacturer, obj.get_producer());
            price = 0;
        }
        operator FoodProd const ()
        {
            FoodProd f(0, manufacturer);
            return f;
        }
}

Input:

FoodProd FP(20, "Ukraine");
IndProd ID("BudMat", 1900, "Germany");
FoodProd FP2;
FP2 = ID;
FP2.print();
IndProd ID2;
ID2 = FP;

Output:

Term of consumption: 0 days.
Manufacturer: ↑r;

Category: ♫      Price: 0$
Manufacturer:
Elgernon
  • 53
  • 1
  • 8
  • 4
    Use a `std::string`. Manual memory management should be left to the library or library implementers. At least use `std::unique_ptr` if you want to use dynamic memory. Don't use owning raw pointers. – Guillaume Racicot May 23 '19 at 14:45
  • @GuillaumeRacicot my teacher forbids me using string, instead I should use pointers. – Elgernon May 23 '19 at 14:47
  • Show a [mcve]. The problem likely lies in the code not shown. – Igor Tandetnik May 23 '19 at 14:48
  • Can you use `std::unique_ptr`? Your runtime error will most likely become a compile time error. – Guillaume Racicot May 23 '19 at 14:48
  • Where are your copy-constructors, for the classes, that you are returning, from functions? – Algirdas Preidžius May 23 '19 at 14:48
  • " IndProd (FoodProd obj)" is fishy, you make a copy of something holding pointers... – OznOg May 23 '19 at 14:49
  • @GuillaumeRacicot No. – Elgernon May 23 '19 at 14:51
  • @Elgernon There is nothing wrong with the code you show. We need more code to help you. You create copies, but we do not know if a proper copy constructor is implemented, or if a destructor exists. For example, if no copy constructor is implemented but the destructor deallocate the memory of the copies, then you will end up with dangling pointers. – Gilles-Philippe Paillé May 23 '19 at 14:59
  • @Gilles-PhilippePaillé I added it but there's nothing wrong with it because I've been working with it for 3 months. – Elgernon May 23 '19 at 15:04
  • 2
    There is something wrong with it: You do not provide `operator=`, but you use it. Please see https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three. – Max Langhof May 23 '19 at 15:11
  • 1
    Look closely at the brackets in the `new`-expressions in `IndProd`'s non-default constructors. – molbdnilo May 23 '19 at 15:12
  • 1
    On an unrelated note, it's perfectly fine to give `delete` a null pointer, so you never need to check that. – molbdnilo May 23 '19 at 15:14
  • @MaxLanghof Should I? It is named implicit conversation. – Elgernon May 23 '19 at 15:20
  • @molbdnilo Oh, yes, thank you. But, honestly, it did not help. – Elgernon May 23 '19 at 15:23
  • 2
    `FP2 = ID;` first converts `ID` to `FoodProd` using `operator FoodProd const`. But then this `FoodProd` must be assigned to `FP2`. This uses `operator=`, which you did not implement, so the compiler auto-generated an incorrect one. As soon as the temporary returned by `FoodProd` dies (right at the end of that line), the incorrectly-copied-via-`operator=` object no longer holds valid pointers and `FP2.print();` prints garbage. Please read the Q/A I linked. – Max Langhof May 23 '19 at 15:28
  • 1
    And as @molbdnilo said, `category = new char(strlen(ind.category) + 1);` is incorrect. This dynamically allocates a _single_ character (with the _value_ `strlen(...)+1`) and then treats it as a string, leading to Undefined Behavior. – Max Langhof May 23 '19 at 15:31
  • @MaxLanghof Yes, I added `operator=` and it worked! Very thankful. – Elgernon May 23 '19 at 15:37

1 Answers1

0

The answer is to provide operator = for both classes.

Elgernon
  • 53
  • 1
  • 8