简体   繁体   中英

Looping through the derived classes by referencing the base class in C++

Sorry, if this has been asked before, just learning C++, had tried to search for it but not sure what the keyword is.

would it possible to do this?

class Car {
   public:
      void addColor(string c) {
          color = c;
      }

   private:
      string color;
}

class Honda:public Car {}
class Toyota:public Car {}

int main() {
    vector<Car> v;

    Honda *car1 = new Honda();
    car1.addColor("green");

    Toyota *car2 = new Toyota();
    car2.addColor("blue");

    v.push_back(car1);
    v.push_back(car2);

    for (int i = 0; i < v.size(); i++) {
        cout << v[i].color << endl; // should output green, blue
    }

}

if it's possible, what is the most right/effective way to do it?

EDIT 1

wow, thank you everybody!

your vector always hold the base type, Car, sliced. Look up for 'polymorphic STL collection' 'polymorphic vector' or like to see how to store the derived classes.

here is an example

There are two ways to handle this. Say we have the following class definitions:

#include <string>
class Car {
   public:
      Car(const std::string& color) : color(color) {}
      virtual ~Car() {}

      std::string color;
};

class Honda:public Car {};
class Toyota:public Car {};

Note I removed the setter and just made the member public. You may or may not want this, but for this example, it doesn't matter. Here is a way by allocating everything on the stack, and taking the address of these objects. This is fine in this example case ( car1 and car2 don't need to outlive the main function). In real code this may not be true (ie the objects may need to outlive the function in which they are created, see further below):

#include <iostream>
#include <vector>

int main() {
    Honda car1("green");
    Toyota car2("blue");
    std::vector<Car*> cars; // vector of non-owning pointers

    v.push_back(&car1);
    v.push_back(&car2);

    for(auto& car : cars) {
        std::cout << car.color << "\n";
    }
}

Alternatively, allocate your objects on the heap:

int main() {
    std::vector<std::unique_ptr<Car>> cars; // vector of owning pointers

    v.emplace_back(new Honda("green"));
    v.push_back(new Toyota("blue"));

    for(auto& carptr : cars) {
        std::cout << carptr->color << "\n";
    }
}

You were on the right way, there were just little things to fix :

  • Add a getter to the base class ( Car );
  • Change the vector type (to a vector<Car*> );
  • Replace ab by a->b when needed;
  • Fix missing semi-colon after classes definitions.

And here you go :

#include <iostream>
#include <vector>

using namespace std;

class Car {
   public:
      virtual ~Car ();
      void addColor(string c) {
          color = c;
      }

      string getColor () {
          return color;
      }

   private:
      string color;
};

class Honda:public Car {};
class Toyota:public Car {};

int main() {
    vector<Car*> v;

    Honda car1;
    car1.addColor("green");

    Toyota car2;
    car2.addColor("blue");

    v.push_back(&car1);
    v.push_back(&car2);

    for (int i = 0; i < v.size(); i++) {
        cout << v[i]->getColor () << endl; // should output green, blue
    }
}

By the way, if you want your subclasses to have their own methods to manipulate the color, just declare the methods as virtual in the car class, and you can redefine it in subclasses.

Another little point. You cannot make your vector be a vector<Car> . Because subclasses might not have the same size as the mother class (Imagine adding a int appeal; to your Honda class), because a vector can only store elements with the same size.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM