Перегрузка оператора C для другого класса ( объект и оператор из класса A используют данные из класса B

#c #class #object #operators

Вопрос:

Я новичок в классах C , объектах и особенно в операторах с завышенной стоимостью.

Учитывая следующую main функцию, я должен обойти ее, чтобы в конце концов программа была правильно скомпилирована и запущена. Вот main функция:

  int main()
{
    TOperator *oper = new TOperator("Alexandru");
    TComanda *command = new TComanda("online", oper);
   command  = new Item("usb stick", 220); // this is calling Item's constructor 
   command  = new Item("tastatura", 175); 
   oper->afiseazaCommanda();// printing out the final cart
   return 0;
 }
 

Основные проблемы, с которыми я сталкиваюсь до сих пор, заключаются в следующем:

1)Как я могу перегрузить = оператор, чтобы я мог сложить строки ( так же, как в python, когда я делаю для двух строк), а также суммировать мои два целых числа?

2)Как я должен написать свою afiseazaComanda() функцию TOperator , чтобы она работала правильно? Потому что до сих пор при попытке его компиляции он выдает мне ошибку « Item не был объявлен в этой области».

Я пытался получить некоторую информацию, global operator overloading но не нашел многого.

Поиск по SO на самом деле не помог, потому что речь не шла о завышении стоимости оператора таким образом, чтобы объект класса TComanda мог завышать стоимость класса Item , поэтому я надеюсь, что смогу найти там какую-то четкую помощь.

Вот код для моих классов:

  class Item
{
public:
    string Product;
    int Price;

    Item(string product, int price)
    {
        Product = product;
        Price = price;
    }
    friend class TComanda;
};

class TOperator
{
    string Name;
public:

    TOperator(string n)
    {
        Name = n;
    }

    void afiseazaComanda()
    {
        cout << Item.Product << " " << Item.Price; // supposed to print out the final cart with both the products and summed prices
    }

    friend class TComanda;
};


class TComanda
{
    string online, name;
public:

    TComanda(string onoroff, TOperator *op)
    {
        online = onoroff;
        this->name = op->Name;
    }

    TComanda operator  =(Item amp;a)
    {
        a =a.Product;
        a =a.Price;
        return *this;
    } // still thinking how I could write that part of the code
};
 

Ответ №1:

Вы не можете реализовать пользовательские операторы для указателей, только для объектов. Так, например, поскольку вы объявили command как TComanda* указатель, вам придется разыменовать command , чтобы получить доступ к TComanda объекту, на который он указывает, например:

 *command  = new Item("usb stick", 220);
 

За исключением того, что вы TComanda:::operator = объявили, что берете Itemamp; ссылку, а не Item* указатель, поэтому вам также придется разыменовать Item* указатель:

 *command  = *(new Item("usb stick", 220));
 

Что является утечкой памяти, так как вы теряете доступ к Item объекту, который вы new редактировали, поэтому вы не можете delete его использовать, когда закончите его использовать (на самом деле, весь ваш main() объект пропускает каждый его объект new ). Итак, избавьтесь от new этого здесь:

 *command  = Item("usb stick", 220);
 

В этом случае вы также можете избавиться от new on command и oper тоже:

 TOperator oper("Alexandru");
TComanda command("online", amp;oper);
command  = Item("usb stick", 220);
command  = Item("tastatura", 175); 
 

Тем не менее, весь ваш дизайн кода является неполным для того, что вы пытаетесь , так как TOperator не имеет понятия TComanda , но даже если бы это было так, TComanda он не хранит свои добавленные Item s в любом месте, которое TOperator может их достичь.

Попробуй это:

 #include <iostream>
#include <vector>
#include <string>
using namespace std;

class Item
{
public:
    string Product;
    int Price;

    Item(const string amp;product, int price);
};

class TComanda;
class TOperator
{
    string Name;
    TComanda *Command = nullptr;

public:
    TOperator(const string amp;name);

    void afiseazaCommanda() const;

    friend class TComanda;
};

class TComanda
{
    string Online, Name;
    vector<Item> Items;
    TOperator amp;Operator;

public:
    TComanda(const string amp;onoroff, TOperator amp;op);
    ~TComanda();

    TComandaamp; operator  =(const Item amp;a);

    friend class TOperator;
};

Item::Item(const string amp;product, int price)
{
    Product = product;
    Price = price;
}

TOperator::TOperator(const string amp;name)
{
    Name = name;
}

void TOperator::afiseazaCommanda() const
{
    if (Command) {
        for(const auto amp;item : Command->Items) {
            cout << item.Product << " " << item.Price << endl;
        }
    }
}

TComanda::TComanda(const string amp;onoroff, TOperator amp;op)
    : Operator(op)
{
    Online = onoroff;
    Name = Operator.Name;
    Operator.Command = this;
}

TComanda::~TComanda()
{
    if (Operator.Command == this)
        Operator.Command = nullptr;
}

TComandaamp; TComanda::operator  =(const Item amp;a)
{
    Items.push_back(a);
    return *this;
}

int main()
{
    TOperator oper("Alexandru");
    TComanda command("online", oper);
    command  = Item("usb stick", 220);
    command  = Item("tastatura", 175); 
    oper.afiseazaCommanda();
    return 0;
}
 

Онлайн-Демонстрация


Обновить:

Учитывая ограничения , которые у вас есть на код main() , попробуйте вместо этого что-нибудь подобное:

 #include <iostream>
#include <vector>
#include <string>
using namespace std;

class Item
{
public:
    string Product;
    int Price;

    Item(const string amp;product, int price);
};

class TComanda;
class TOperator
{
    string Name;
    TComanda *Command = nullptr;

public:
    TOperator(const string amp;name);

    void afiseazaCommanda() const;

    friend class TComanda;
};

class TComanda
{
    string Online, Name;
    vector<Item*> Items;
    TOperator *Operator;

public:
    TComanda(const string amp;onoroff, TOperator *op);
    ~TComanda();

    TComandaamp; operator  =(Item *a);

    friend class TOperator;
};

Item::Item(const string amp;product, int price)
{
    Product = product;
    Price = price;
}

TOperator::TOperator(const string amp;name)
{
    Name = name;
}

void TOperator::afiseazaCommanda() const
{
    if (Command) {
        for(const auto *item : Command->Items) {
            cout << item->Product << " " << item->Price << endl;
        }
    }
}

TComanda::TComanda(const string amp;onoroff, TOperator *op)
{
    Online = onoroff;
    Operator = op;
    Name = Operator->Name;
    Operator->Command = this;
}

TComanda::~TComanda()
{
    for(auto *item : Items)
        delete item;
        
    if (Operator->Command == this)
        Operator->Command = nullptr;
}

TComandaamp; TComanda::operator  =(Item *a)
{
    Items.push_back(a);
    return *this;
}

int main()
{
    TOperator *oper = new TOperator("Alexandru");
    TComanda *command = new TComanda("online", oper);
    *command  = new Item("usb stick", 220);
    *command  = new Item("tastatura", 175); 
    oper->afiseazaCommanda();
    delete command;
    delete oper;
    return 0;
}
 

Онлайн-Демонстрация

Комментарии:

1. спасибо вам за вашу помощь, но проблема в том, что я должен обходить эту main функцию как есть, потому что это то, что мне было поручено. Я связался по этому поводу со своим преподавателем, но, зная его, он может не ответить до следующего занятия с ним.

2. » Я должен обойти эту основную функцию как есть, потому что это то, что мне было назначено » — Затем вам был дан плохой код для начала, так как он не может работать так, как показано, по причинам, которые я изложил. Я скорректировал свой ответ, чтобы он работал с вашими ограничениями, но эти ошибки необходимо устранить, иначе все это спорно.

3. Спасибо вам за вашу помощь, это действительно сработало.

4. Не могли бы вы объяснить, пожалуйста, почему вы поместили amp; имена переменных перед во все 3 конструктора? Каким образом это помогает нам? Я действительно ничего не замечаю, потому что, как я знал, это должно было прекрасно сработать даже без этого. Просто спрашиваю из любопытства

5. @Влад, Ты не сказал, какую версию C ты используешь. До добавления семантики перемещения в C 11 было более эффективно передавать std::string по ссылке, чем по значению. Но в C 11 и более поздних версиях это уже не имеет особого значения. Но все равно неплохо передать объект по ссылке, если вы не собираетесь копировать/перемещать его.