C++ 用抽象 class 重载输入
C++ Overloading input with abstract class
我正在尝试构建一个 "candy shop user interface" 并且我有 4 个 classes:
SweetItem class - 抽象基础 class
Candy, Cookie, IceCream classes - 派生自基数 class 实际上
Cookielida - 来自饼干和冰淇淋 classes
现在我在基地class:
class SweetItem
{
public:
/*=====Builders & Destructor & = Operator=====*/
SweetItem();
SweetItem(const SweetItem&);
~SweetItem();
const SweetItem& operator=(const SweetItem&);
/*=====Input\Output operators=====*/
friend ostream& operator<<(ostream&, const SweetItem&);
friend istream& operator>>(istream&, SweetItem&);
/*=====Static members=====*/
static void NoSweets() { cout << num_sweets; }
static int get_num() { return num_sweets; }
/*=====Virtual Interface=====*/
virtual SweetItem* clone() const = 0;
virtual SweetItem* enter() = 0;
virtual void print() const = 0;
virtual int get_amount() const =0;
virtual float get_price() const = 0;
virtual String get_type() const = 0;
virtual float get_total() const = 0;
/*=====Cyber Function=====*/
void color(const int) const;
protected:
private:
static int num_sweets;
};
input/output 正在调用虚函数 "enter()" 和 "print()":
ostream& operator<<(ostream& op, const SweetItem& input) {
if(&input)
input.print();
return op;
}
istream& operator>>(istream& ip, SweetItem& input) {
input.enter();
return ip;
}
当我尝试像这样使用 cookielida 的 "enter()" 时:
int main() {
SweetItem* temp = new Cookielida;
cin >> *temp;
cout << *temp << endl;
}
它打印我设置的默认对象而不是用户输入的选择。这是虚拟实现:
SweetItem* Cookielida::enter() {
String ct, it;
float cp, ip;
cout << "Please select from the available options: " << endl;
cout << "1) Butter cookies " << BUTTERP << "$ per unit" << endl;
cout << "2) Chocolate chip cookies " << CHIPP << "$ per unit" << endl;
cout << "3) Oreo cookies " << OREOP << "$ per unit" << endl;
int opt1;
opt1 = error(1, 3);
switch (opt1)
{
case BUTTER: ct = "Butter cookies";
cp = BUTTERP;
break;
case CHIP: ct = "Chocolate chip cookies";
cp = CHIPP;
break;
case OREO: ct = "Oreo cookies";
cp = OREOP;
break;
default:
break;
}
cout << "Please select from the available options: " << endl;
cout << "1) Vanilla icecream " << VANIP << "$ per unit" << endl;
cout << "2) Chocolate icecream " << CHOCP << "$ per unit" << endl;
cout << "3) Yogurt icecream " << YOGUP << "$ per unit" << endl;
int opt2;
opt2 = error(1, 3);
switch (opt2)
{
case VANI: it = "Vanilla icecream";
ip = VANIP;
break;
case CHOC: it = "Chocolate icecream";
ip = CHOCP;
break;
case YOGU: it = "Yogurt icecream";
ip = YOGUP;
break;
default:
break;
}
cout << "How many cookielidas do you want? " << endl;
int a;
a = error(0, MAXAMOUNT);
SweetItem* temp = new Cookielida(a, ip, cp, it, ct);
return temp;
}
我认为问题在于 "enter()" 函数中创建的临时 cookielida 被销毁而不是复制到 "main()" 中的临时文件。
这些也是构造函数:
Cookielida::Cookielida(int a=0, float ip=0, float cp=0, const String& it="", const String& ct="") :
IceCream(ICEA, ip, it), Cookie(COKA, cp, ct), amount(a), price((ip + cp * 2)*1.5), type(ct + " " + it)
{
}
Cookielida::Cookielida(const Cookielida& input) :
IceCream(ICEA, input.get_ip(), input.get_it()),
Cookie(COKA, input.get_cp(), input.get_ct()),
amount(input.amount), price(input.price), type(input.type)
{
}
这是输出:
问题出在您的 enter()
函数中。它不会更改对象本身,而是创建一个新对象,该对象通过指针 returned。因此,当您在 operator>>
重载中调用 input.enter();
时, class input
所指的是不变的——事实上,当您 return 根本没用。
作为解决方法,您可以执行以下操作
Cookielida& Cookielida::enter() //better return the derived object in a covariant way,
//not the base class pointer
//you can still downcast it if required
{
//read in those many parameters
//then either set the class member variables "a, ip, cp, it, ct"
//directly (--the preferred way)
//or use this cheap alternative
operator=(Cookielida(a, ip, cp, it, ct));
return *this;
}
您完全错过了 Cookielida::enter
函数设计的要点。它 returns 完全是新对象,不会更改旧对象。
把它放在 operator>>
里面是胡说八道,你可能真的想把它放在其他地方。
int main() {
SweetItem* temp = new Cookielida;
SweetItem* temp2 = temp->enter();
temp2->print();
delete temp;
delete temp2;
}
我正在尝试构建一个 "candy shop user interface" 并且我有 4 个 classes:
SweetItem class - 抽象基础 class
Candy, Cookie, IceCream classes - 派生自基数 class 实际上
Cookielida - 来自饼干和冰淇淋 classes
现在我在基地class:
class SweetItem
{
public:
/*=====Builders & Destructor & = Operator=====*/
SweetItem();
SweetItem(const SweetItem&);
~SweetItem();
const SweetItem& operator=(const SweetItem&);
/*=====Input\Output operators=====*/
friend ostream& operator<<(ostream&, const SweetItem&);
friend istream& operator>>(istream&, SweetItem&);
/*=====Static members=====*/
static void NoSweets() { cout << num_sweets; }
static int get_num() { return num_sweets; }
/*=====Virtual Interface=====*/
virtual SweetItem* clone() const = 0;
virtual SweetItem* enter() = 0;
virtual void print() const = 0;
virtual int get_amount() const =0;
virtual float get_price() const = 0;
virtual String get_type() const = 0;
virtual float get_total() const = 0;
/*=====Cyber Function=====*/
void color(const int) const;
protected:
private:
static int num_sweets;
};
input/output 正在调用虚函数 "enter()" 和 "print()":
ostream& operator<<(ostream& op, const SweetItem& input) {
if(&input)
input.print();
return op;
}
istream& operator>>(istream& ip, SweetItem& input) {
input.enter();
return ip;
}
当我尝试像这样使用 cookielida 的 "enter()" 时:
int main() {
SweetItem* temp = new Cookielida;
cin >> *temp;
cout << *temp << endl;
}
它打印我设置的默认对象而不是用户输入的选择。这是虚拟实现:
SweetItem* Cookielida::enter() {
String ct, it;
float cp, ip;
cout << "Please select from the available options: " << endl;
cout << "1) Butter cookies " << BUTTERP << "$ per unit" << endl;
cout << "2) Chocolate chip cookies " << CHIPP << "$ per unit" << endl;
cout << "3) Oreo cookies " << OREOP << "$ per unit" << endl;
int opt1;
opt1 = error(1, 3);
switch (opt1)
{
case BUTTER: ct = "Butter cookies";
cp = BUTTERP;
break;
case CHIP: ct = "Chocolate chip cookies";
cp = CHIPP;
break;
case OREO: ct = "Oreo cookies";
cp = OREOP;
break;
default:
break;
}
cout << "Please select from the available options: " << endl;
cout << "1) Vanilla icecream " << VANIP << "$ per unit" << endl;
cout << "2) Chocolate icecream " << CHOCP << "$ per unit" << endl;
cout << "3) Yogurt icecream " << YOGUP << "$ per unit" << endl;
int opt2;
opt2 = error(1, 3);
switch (opt2)
{
case VANI: it = "Vanilla icecream";
ip = VANIP;
break;
case CHOC: it = "Chocolate icecream";
ip = CHOCP;
break;
case YOGU: it = "Yogurt icecream";
ip = YOGUP;
break;
default:
break;
}
cout << "How many cookielidas do you want? " << endl;
int a;
a = error(0, MAXAMOUNT);
SweetItem* temp = new Cookielida(a, ip, cp, it, ct);
return temp;
}
我认为问题在于 "enter()" 函数中创建的临时 cookielida 被销毁而不是复制到 "main()" 中的临时文件。 这些也是构造函数:
Cookielida::Cookielida(int a=0, float ip=0, float cp=0, const String& it="", const String& ct="") :
IceCream(ICEA, ip, it), Cookie(COKA, cp, ct), amount(a), price((ip + cp * 2)*1.5), type(ct + " " + it)
{
}
Cookielida::Cookielida(const Cookielida& input) :
IceCream(ICEA, input.get_ip(), input.get_it()),
Cookie(COKA, input.get_cp(), input.get_ct()),
amount(input.amount), price(input.price), type(input.type)
{
}
这是输出:
问题出在您的 enter()
函数中。它不会更改对象本身,而是创建一个新对象,该对象通过指针 returned。因此,当您在 operator>>
重载中调用 input.enter();
时, class input
所指的是不变的——事实上,当您 return 根本没用。
作为解决方法,您可以执行以下操作
Cookielida& Cookielida::enter() //better return the derived object in a covariant way,
//not the base class pointer
//you can still downcast it if required
{
//read in those many parameters
//then either set the class member variables "a, ip, cp, it, ct"
//directly (--the preferred way)
//or use this cheap alternative
operator=(Cookielida(a, ip, cp, it, ct));
return *this;
}
您完全错过了 Cookielida::enter
函数设计的要点。它 returns 完全是新对象,不会更改旧对象。
把它放在 operator>>
里面是胡说八道,你可能真的想把它放在其他地方。
int main() {
SweetItem* temp = new Cookielida;
SweetItem* temp2 = temp->enter();
temp2->print();
delete temp;
delete temp2;
}