#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 и более поздних версиях это уже не имеет особого значения. Но все равно неплохо передать объект по ссылке, если вы не собираетесь копировать/перемещать его.