Cout Overload работает для множественного наследования - PullRequest
0 голосов
/ 16 апреля 2020

У меня есть 4 класса: Транспортное средство, Пассажирский транспорт, Грузовой автомобиль и Экипаж. Я нарисую диаграмму и помещу элементы данных в круглые скобки.

                                 Vehicle
                            (model, brand, year)
                        /                         \
                       /                           \
(model, brand, year, doors, seats)          (model, brand, year, capacity)
           PassengerVehicle                           CargoVehicle
                        \                         /
                         \                       /
                                 CrewHauler
                  (model, brand, year, doors, seats, capacity)

Все работает отлично. Но когда я пытаюсь написать оператор перегрузки "cout <<" для CrewHauler, он продолжает говорить, что "объект имеет спецификатор типа, который не совместим с функцией-членом" passengerVehicle :: getDoors "" и подчеркивает <em>CrewHauler .getDoors (), а также CrewHauler .getSeats (). Как мне это исправить? Вот мой код:


using namespace std;

CrewHauler::CrewHauler(std::string brand, std::string model, int year, 
                       int doors, int seats, double capacity) : 
                       passengerVehicle(brand, model, year, doors, seats), 
                       cargoVehicle(brand, model, year, capacity)
{
}

std::ostream& operator<<(std::ostream& output, const CrewHauler& CrewHauler)
{
    output << "------- CrewHauler -------" << endl
        << "Brand: " << CrewHauler.Vehicle::getBrand() << endl
        << "Model: " << CrewHauler.Vehicle::getModel() << endl
        << "Year: " << CrewHauler.Vehicle::getYear() << endl 
        << "Doors:" << CrewHauler.getDoors() << endl
        << "Seats:" << CrewHauler.getSeats() << endl;
    return output;
}

1 Ответ

0 голосов
/ 16 апреля 2020

Я воспроизвел ваши сущности следующим образом (при условии использования не виртуальных методов publi c наследования и publi c) и получил 2 ошибки компиляции. Первый касался неоднозначности вызова метода, поскольку компилятор не знает, какой путь использовать для достижения Vechicle::getBrand, второй говорил, что он не может преобразовать тип const CrewHauler в тип Vehicle&.

class Vehicle {
public:
    int getBrand() { return 1; }
};

class PassengerVehicle : public Vehicle {
public:
    int getBrand() { return 2; }
};

class CargoVehicle : public Vehicle {
public:
    int getBrand() { return 3; }
};

class CrewHauler : public PassengerVehicle, public CargoVehicle {
public:
    int getBrand() { return 4; }
};

std::ostream& operator<<(std::ostream& _o, const CrewHauler& _h) {
    return _o << _h.Vehicle::getBrand();
}

Чтобы решить первый, я просто указал полный путь, которым должен следовать компилятор, чтобы достичь желаемого getBrand метода: _h.CargoVehicle::Vehicle::getBrand() (вы также можете использовать _h.PassengerVehicle::Vehicle::getBrand(), поскольку конечная точка одинакова ).

Я не думаю, что есть способ решить вторую ошибку, которая вызвана вызовом базового метода, используя только одну перегрузку оператора, которая может принимать как lvalues, так и rvalues ​​вашей сущности. поэтому я делю его на 2, один из которых принимает неконстантный тип lvalue-reference (CrewHauler&), а другой - (неконстантный) тип rvalue-reference (CrewHauler&&):

std::ostream& operator<<(std::ostream& _o, CrewHauler& _h) {
    return _o << _h.CargoVehicle::Vehicle::getBrand() << " lvalue reference";
}

std::ostream& operator<<(std::ostream& _o, CrewHauler&& _h) {
    return _o << _h.PassengerVehicle::Vehicle::getBrand() << " rvalue reference";
}

Я написал этот пример кода, чтобы проверить его:

auto ch = CrewHauler();
std::cout << CrewHauler() << std::endl << ch;

, который выведет следующее, как и ожидалось:

1 ссылка на значение
1 ссылка на значение

Надеюсь, это поможет.

...