1

C++ で;

関数がオーバーライドされていない場合でも、基本クラスを介して派生クラスから関数を呼び出す方法はありますか? 言い換えれば、ブーストなしで異種のコンテナを持つために基本クラスを使用しています。派生クラスだけに固有のメンバー関数を呼び出したい...

例: (このコードを作成したばかりなので、構文エラーがある可能性がありますが、要点を理解していただければ幸いです)

class Vehicle
{
  public:
   virtual void do_vehicle_stuff();
   // virtual void do_car_specific_stuff(); makes no sense here
}

class Car : public Vehicle
{
  public:
   void do_vehicle_stuff();
   void do_car_specific_stuff();
}

Car a,b;

list<Vehicle> vehicle_list;
vehicle_list.push_back(a);
vehicle_list.push_back(b);

vehicle_list.front().do_car_specific_stuff();

エラー: 'Class Vehicle' には 'do_car_specific_stuff()' という名前のメンバーがありません

4

2 に答える 2

1

クラスをリストに挿入すると、クラスがスライスされます。C++ サブタイプ ポリモーフィズム (使用している種類のポリモーフィズム) では、参照またはポインターを介してのみ機能し、値は機能しません。に挿入するcarSと、listに変換されVehicleSます。

例:

Car c;
std::vector<Vehicle> vs;
vs.push_back(c); // slicing happens
vs.front(); // not a car anymore, but just a vehicle,
            // the Car-ness is lost through the copy operation

それを行う方法:

std::vector<std::unique_ptr<Vehicle>> vs;
vs.push_back(new Car());
vs.front(); // actually a Car

コードの根本的な欠陥を解決したら、次のことが役立つ可能性があります。

Vehicle* vehiclep = new Car();
if(auto carp = dynamic_cast<Car*>(vehiclep)) {
  carp->do_car_specific_stuff();
}

これはかなりコストのかかる操作であり、通常はデザインの臭いを示しているため、実行していることを再考することをお勧めします。

于 2012-12-03T01:11:53.853 に答える
1

より適切な設計は次のとおりです。

struct Vehicle
{
    virtual ~Vehicle() { }

    void do_vehicle_stuff()
    {
        vehicle_impl();
    }

private:
    virtual void vehicle_impl() = 0;
};

struct Car : Vehicle
{
private:
    virtual void vehicle_impl()
    {
        my_vehicle_stuff();
        my_car_specific_stuff();
    }

    void my_vehicle_stuff()      { /* what you had originally */ }
    void my_car_specific_stuff() { /* car-only stuff */ }
};

std::list<std::unique_ptr<Vehicle>> vehicles;

vehicles.emplace_back(new Car);
vehicles.emplace_back(new Motorcycle);
vehicles.emplace_back(new Carriage);
于 2012-12-03T01:15:12.947 に答える