为什么调用 `getNoise` 的时候使用了基类实现而不是子类实现?

huangapple go评论71阅读模式
英文:

Why does this call to `getNoise` use the base class implementation and not the subclass implementation?

问题

问题

我的理解是,通过在基类中将 getNoise 声明为虚拟函数,然后在任何子类中重写它,我们可以实现多态性。然后,通过指针的向量,我们存储基类的地址,用于调用诸如 getNoise 之类的方法。

有人能告诉我为什么我的代码没有做到这一点吗?

代码

#include <iostream>
#include <vector>
#include <memory>

using namespace std;

class Animals {
private:
    std::string noise = "None";

public:
    Animals() = default;

    virtual ~Animals() = default;

    virtual std::string getNoise() {
        return noise;
    }
};

class Duck : public Animals {
private:
    std::string noise = "Quack!";
public:
    using Animals::Animals;

    std::string getNoise() override {
        return noise;
    }
};

class Dog : public Animals {
private:
    std::string noise = "Bark!";
public:
    using Animals::Animals;

    std::string getNoise() override {
        return noise;
    }
};

class AnimalsContainer {
public:
    std::vector<Animals *> animals;
    Animals *front;

    AnimalsContainer() {
        Duck duck;
        Dog dog;
        animals.push_back(&duck);
        animals.push_back(&dog);
        front = animals[0];
    }

    ~AnimalsContainer() = default;
};

int main() {
    AnimalsContainer animals;
    cout << animals.front->getNoise() << endl;
}

预期输出

我期望得到

Quack!

但我得到了

None

请问有什么问题?

英文:

The problem

My understanding was that we could achieve polymorphim by making getNoise virtual in the base, and then overriding it in any subclasses. Then via a vector of pointers, we store the address of the base classes which are used to call methods on such as getNosie below.

Could anybody tell me why my code doesn't do this?

The code

#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;memory&gt;

using namespace std;


class Animals {
private:
    std::string noise = &quot;None&quot;;

public:
    Animals() = default;

    virtual ~Animals() = default;

    virtual std::string getNoise() {
        return noise;
    }

};

class Duck : public Animals {
private:
    std::string noise = &quot;Quack!&quot;;
public:
    using Animals::Animals;

    std::string getNoise() override {
        return noise;
    }
};

class Dog : public Animals {
private:
    std::string noise = &quot;Bark!&quot;;
public:
    using Animals::Animals;

    std::string getNoise() override {
        return noise;
    }
};


class AnimalsContainer {
public:
    std::vector&lt;Animals *&gt; animals;
    Animals *front;

    AnimalsContainer() {
        Duck duck;
        Dog dog;
        animals.push_back(&amp;duck);
        animals.push_back(&amp;dog);
        front = animals[0];
    }

    ~AnimalsContainer() = default;
};


int main() {
    AnimalsContainer animals;
    cout &lt;&lt; animals.front-&gt;getNoise() &lt;&lt; endl;

Expected output

I'm expecting

Quack!

But I'm getting

None

答案1

得分: 2

"std::string noise"应该只在基类中声明,而不是在子类中声明。应该在子类的构造函数中设置噪声值。

英文:

"std::string noise" should only be declared in the base class, not in the subclasses. Set the noise value in the constructors of the subclasses instead.

答案2

得分: 1

为什么不使用指针:

Duck* duck = new Duck();
Dog* dog = new Dog();
animals.push_back(duck);
animals.push_back(dog);

而不是

Duck duck;
Dog dog;
animals.push_back(&duck);
animals.push_back(&dog);

然后你可以在析构函数中销毁它们:

~AnimalsContainer() {
    for (Animal* a : animals) {
        delete a;
    }
}

如果你真的需要在基类中使用字符串 "none"。

当然,原始指针是为了简单起见,你也可以考虑使用智能指针。

英文:

Why dont't you use pointers:

Duck* duck = new Duck();
Dog* dog = new Dog();
animals.push_back(duck);
animals.push_back(dog);

Instead of

Duck duck;
Dog dog;
animals.push_back(&amp;duck);
animals.push_back(&amp;dog);

You can then destroy them on the destructor:

~AnimalsContainer() {
    for (Animals* a : animals) {
        delete a;
    }
}

If you really need noise string "none" in the base class.

Of course the raw pointers are for simplicity, you should maybe use smart pointers.

huangapple
  • 本文由 发表于 2020年1月7日 00:36:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/59615767.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定