не может вызвать функцию для члена класса - PullRequest
0 голосов
/ 21 июня 2020

В следующем примере, почему я не могу вызвать car.getFuelConsvention

class Road {
public:
    double length(); // km
    int speed(); // km per hour ;
};

class Car {
protected:
    virtual double getFuelConsumption(int speed_in_km) = 0;
};

class Tank: public Car{
public:
    double getFuelConsumption(int speed_in_km) {
        return 1;
    }
};

double getPetrol(std::vector<Road> roads, const Car &car) {
    double total_fuel_consumption=0;
    for (int i=0;i<roads.size();++i)
    {
        double fuel_consumption_per_road = car.getFuelConsumption(roads[i].speed());
    }
    return total_fuel_consumption;
}

У каждой машины есть такой метод, так почему я не могу его вызвать? Например, если я отправлю Tank на getPetrol(), я ожидаю, что он сработает, и вызову версию Tank getFuelConsumption()

Undefined symbols for architecture x86_64:   "Road::speed()", referenced from:
getPetrol(std::__1::vector<Road, std::__1::allocator<Road> >, Car const&) 
in main.cpp.o ld: symbol(s) not found for architecture
x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)

Ответы [ 2 ]

1 голос
/ 21 июня 2020

Видимые проблемы с вашим кодом следующие:

  • getPetrol() определяется вне класса и вызывает защищенный член getFuelConsumption(), защищенные члены не могут быть вызваны вне класса.

    Чтобы исправить это, вы делаете getFuelConsumption() метод public в базовом классе.

  • Потому что у вас есть аргумент объекта const const Car &car, метод getFuelConsumption() должен иметь const return, const объекты не могут вызывать неконстантные методы. Вы также можете удалить ключевое слово const из аргумента car, но в этом случае подходит первый вариант.

  • Поскольку вы собираетесь использовать ссылки абстрактного базового класса на производные классы, эффективный полиморфизм, также рекомендуется использование виртуального деструктора, под угрозой вызова неопределенного поведения.

  • Ошибка компоновщика, о которой вы говорите, может быть вызвана тем, что объявлены методы Road, но не определено, по крайней мере, в коде, который вы показываете.

Исправленный код:

Живая демонстрация

#include <iostream>
#include <vector>

class Road {
public:
    double length(){ return 0;} // added function body to avoid linker error
    int speed(){ return 0; }    // ""  
};

class Car {
public:
    virtual double getFuelConsumption(int speed_in_km) const = 0;
    virtual ~Car(){} //virtual destructor
};

class Tank : public Car {
public:
    double getFuelConsumption(int speed_in_km) const {
        return speed_in_km;
    }
};

double getPetrol(std::vector<Road> roads, const Car &car) {
    double total_fuel_consumption = 0;
    for (size_t i = 0; i < roads.size(); ++i) {
        total_fuel_consumption += car.getFuelConsumption(roads[i].speed());
    }
    return total_fuel_consumption;
}
0 голосов
/ 21 июня 2020

автомобиль - это const, но метод не const. Вы не можете вызвать неконстантный метод для константного объекта. См. https://www.learncpp.com/cpp-tutorial/810-const-class-objects-and-member-functions/

...