C++ 用抽象 class 重载输入

C++ Overloading input with abstract class

我正在尝试构建一个 "candy shop user interface" 并且我有 4 个 classes:

  1. SweetItem class - 抽象基础 class

  2. Candy, Cookie, IceCream classes - 派生自基数 class 实际上

  3. 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;
}