C ++ можно условно снизить указатель класса? - PullRequest
2 голосов
/ 30 октября 2019

У меня есть базовый класс (робот), и в зависимости от аргументов, передаваемых программе, я хочу уменьшить указатель робота на определенный производный класс. класс робота имеет виртуальные функции, которые определены в каждом из производных классов.

До сих пор я мог создать указатель базового класса и в рамках условного оператора создать производный класс, который затем динамически становится базовым. приведение к. Внутри условного указатель работает как задумано, но после выхода из условного оператора производный класс выходит за рамки видимости и функции возвращаются в виртуальный. Есть ли способ, которым я могу сохранить указатель на производный класс?

class vehicles{
    public:
        virtual void print_state(int state_ind, ofstream& file){}
};

class hovercraft : public vehicles{
    public:
        hovercraft(
            int L_in, int W_in, 
            double start_x, double start_y, 
            double goal_x, double goal_y)
        {
            L = L_in;
            W = W_in;
            start_state.x = start_x;
            start_state.y = start_y;
            goal_state.x = goal_x;
            goal_state.y = goal_y;
            Tree.push_back(start_state);
        }

        void print_state(int state_ind, ofstream& file){
            state s = Tree[state_ind];

            file<<s.phi<<","<<
                s.u<<","<<
                s.v<<","<<
                s.r<<","<<
                s.x<<","<<
                s.y<<"\n";
        }

    private:
        struct state{
            double g=0;
            double u=0;
            double v=0;
            double r=0;
            double x=0;
            double y=0;
            double phi=0;
            int p=0;
        };

        int L,W;
        state start_state, goal_state, state_sample;
        vector<state> Tree;
    };

int main(int argc, char* argv[])
{   
    ifstream infile;
    string vehicle_name;
    vehicles* vehicle;
    int start, goal;
    for(int i=0; i < argc; i++){
        if (string(argv[i])=="-m"){
            infile.open (argv[i+1]);
        } else if (string(argv[i])=="-v"){
            vehicle_name = string(argv[i+1]);
        } 
    }

    ofstream file_out;
    file_out.open ("state.csv");
    if(vehicle_name == "hovercraft"){
        int L, W;
        double start_x, start_y, goal_x, goal_y;
        infile >> L;
        infile >> W;
        infile >> start_x;
        infile >> start_y;
        infile >> goal_x;
        infile >> goal_y;

        hovercraft my_vehicle(L,W, start_x, start_y, goal_x, goal_y);
        hovercraft* vehicle = dynamic_cast<hovercraft*>(&my_vehicle);
    } else {
        cout<<"Invalid Vehicle: "<<vehicle_name<<"\n Exiting...\n";
        return 0;
    }

    vehicle->print_state(0);
}

Это упрощено от фактического кода, но я думаю, что это захватывает проблему. В результате я хочу, чтобы print работала одинаково внутри оператора if и после него, но после него всегда будет печататься «no vehicle».

1 Ответ

2 голосов
/ 30 октября 2019

Вы перегружаете переменную rptr внутри области действия ваших операторов if, которая скрывает объявленную в начале main. Таким образом, ваше окончательное значение rptr->print() является неопределенным поведением, поскольку вы вызываете виртуальную функцию по неинициализированному указателю.

Просто удалите перегрузку следующим образом:

robot *rptr = nullptr;

if (*argv[1] == 'h')       // <-- also fixed this (yours was broken)
{
    rptr = new hovercraft();
    rptr->print();
}
else if (*argv[1] == 'q')  // <-- also fixed this (yours was broken)
{
    rptr = new quadrotor();
    rptr->print();
}
else
{
    std::cout << "Invalid vehicle input" << std::endl;
}

if (rptr)
{
    rptr->print(); 
}

Возможно, вы также захотитерассмотрите возможность использования std::shared_ptr или std::unique_ptr (вместе с std::make_shared или std::make_unique) для правильного управления временем жизни динамической памяти.

...