C ++使用抽象类重载输入

时间:2015-05-21 12:17:08

标签: c++ inheritance virtual virtual-inheritance

我正在尝试建立一个“糖果店用户界面”,我有4个班级:

  1. SweetItem类 - 抽象基类

  2. Candy,Cookie,IceCream类 - 实际上来自基类

  3. Cookielida - 来自饼干和冰淇淋类

  4. 现在我已经进入了基类:

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

    输入/输出调用虚函数“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()”函数中创建的temp cookieli被破坏而不是复制到“main()”中的temp。 这些也是构造函数:

    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 image description here

2 个答案:

答案 0 :(得分:1)

问题出在您的enter()功能中。它不会改变对象本身,而是创建一个通过指针返回的新对象。因此,当您在input.enter();重载中调用operator>>时,类input引用的内容不会发生变化 - 实际上,没有任何反应,因为您返回的指针根本不会被使用。< / p>

作为解决方法,您可以执行以下操作

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

答案 1 :(得分:0)

您完全错过了Cookielida::enter功能设计的重点。它返回完全新对象并且不会更改旧对象。 把它放在operator>>里面只是一个废话,你可能实际上想把它放在其他地方。

int main() {
    SweetItem* temp = new Cookielida;
    SweetItem* temp2 = temp->enter();
    temp2->print();
    delete temp;
    delete temp2;
}