如何使用多态性从基类访问派生类向量成员?

2022-01-24 00:00:00 inheritance polymorphism vector c++

It's said that with polymorphism, we can access a derived class member field with it's base class object like this:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Tool{
    public:
        Tool(){}
        Tool(string name){
            this->name = name;
        }
        virtual string getInfo(){
            return name;
        }
    //protected:
        string name;
};

class Computer: public Tool{
    public:
        Computer(string name, int price){
            this->name = name;
            this->price = price;
        }
        virtual string getInfo(){
            return name + ": " + to_string(static_cast<long long>(price));
        }
    //protected:
        int price;
};

class Person{
    public:
        Person(){}
        Person(string name){
            this->name = name;
        }
        virtual string getInfo(){
            return name;
        }
        virtual void addTools(Computer cmp){
            tools.push_back(cmp);
        }
    //protected:
        vector<Tool> tools;
        string name;
};

class Programmer: public Person{
    public:
        Programmer(string name, string job){
            this->name = name;
            this->job = job;
        }
        string getInfo(){
            return name + ": " + job;
        }
    //protected:
        string job;
};

int main(){
    Person prs("Person");
    Programmer prg("Daphloon", "programmer");

    Person* prs1 = &prs;
    Person* prs2 = &prg;

    cout << prs1->getInfo() << endl;    // result: Person
    cout << prs2->getInfo() << endl;    // result: Daphoon: programmer

    Tool tl("Hammer");
    Computer cmp("PC", 100);

    Tool* tl1 = &tl;
    Tool* tl2 = &cmp;


    cout << tl1->getInfo() << endl;     // result: Hammer
    cout << tl2->getInfo() << endl;     // result: PC: 100

    prs2->addTools(cmp);

    cout << prs2->tools[0].getInfo() << endl;   // result: PC
                                                // I expect the result will be: PC: 100 

    return 0;
}

The result wasn't what I expected. What I need is every derived class from Person have a vector tools that contains object that inherit from Tool class. If it described with word, it will be, "This Person, a Programmer, has some tools. His first Tool is a Computer. If you want to know what's it's price, use getInfo()."

  1. Why vector take the base class instead of the derived class?
  2. Is there any data loss from cmp object when i put it inside tools vector?
  3. Is this happen because tools vector member take Tool as it's type?

解决方案

Runtime polymorphism in C++, achieved via virtual functions, works on covariant types. The only covariant types are pointers and references. Since you have a vector<Tool>, you lose polymorphism. To retain it, store a vector<Tool*>. Even better, store a vector<unique_ptr<Tool>>.

Assigning a derived class object to a base class is called object slicing. You do lose information contained in the derived object. This is the case when you are inserting a Computer into a vector<Tool>.

相关文章