C++ 用抽象类重载输入

标签 c++ inheritance virtual virtual-inheritance

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

  1. SweetItem 类 - 抽象基类

  2. Candy、Cookie、IceCream 类 - 几乎从基类派生

  3. Cookielida - 派生自 cookies 类和冰淇淋类

现在我在基类中有:

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()”函数中创建的临时 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 image description here

最佳答案

问题出在您的 enter() 函数中。它不会改变对象本身,而是创建一个通过指针返回的新对象。因此,当您在 operator>> 重载中调用 input.enter(); 时,input 所指的类不会发生变化——并且在事实上,没有任何事情发生,因为您返回的指针根本没有被使用。

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

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

关于C++ 用抽象类重载输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30373516/

相关文章:

c++ - 将 native 缓冲区包装器转换为 C++/CLI

c++ - 带有子类容器的子类的非标准迭代器

c++ - 我们可以访问纯虚类的静态成员变量吗?

C++ 如何初始化 std::istream* 尽管构造函数受到保护

c++ - SFINAE 不能防止不明确的运算符重载吗?

c++ - 在C++中,接受基类的构造函数算作复制构造函数吗?

java - 为什么调用接口(interface)继承的方法需要强制转换?

scala - 成员函数默认为虚函数

c# - 为什么 Rhino.Mocks 和 Moq 说 Bar 是不可覆盖的成员?

c++ - OpenCV (CvHaarClassifierCascade*) cvLoad 不加载,无法加载 xml 文件