Доступ к виртуальным классам в C ++ - PullRequest
0 голосов
/ 16 января 2020

Я пытаюсь понять виртуальные классы в C ++. В Википедии я нашел этот пример:

#include <iostream>

class Machine {
public:
    void run() { }

    class Parts {
    public:
        virtual int get_wheels() = 0;

        virtual std::string get_fuel_type() = 0;
    };
};

// The inner class "Parts" of the class "Machine" may return the number of wheels the machine has.
class Car: Machine {
public:
    void run() { 
        std::cout << "The car is running." << std::endl; 
    }

    class Parts: Machine::Parts {
    public:
        int get_wheels() override {
            std::cout << "A car has 4 wheels." << std::endl;
            return 4;
        }

        std::string get_fuel_type() override {
            std::cout << "A car uses gasoline for fuel." << std::endl;
            return "gasoline";
        }
    };
};

Я могу получить количество колес автомобиля с помощью:

Car::Parts c_p;
c_p.get_wheels();

Есть ли другие (простые ) путь? Есть ли способ создания только Car car?

Обновление:

Я понимаю проблемы, но считаю его полезным в качестве вложенного интерфейса (с минимальными изменениями):

#include <iostream>
#include <memory>

class Machine {
public:
    virtual void run() = 0;

    class Parts {
    public:
        virtual int get_wheels() = 0;
        virtual std::string get_fuel_type() = 0;
    };
};

class Car: public Machine {
public:
    void run() { 
        std::cout << "The car is running." << std::endl; 
    }

    class Parts: public Machine::Parts {
    public:
        int get_wheels() override {
            std::cout << "A car has 4 wheels." << std::endl;
            return 4;
        }

        std::string get_fuel_type() override {
            std::cout << "A car uses gasoline for fuel." << std::endl;
            return "gasoline";
        }
    };
};

int main () {
    std::shared_ptr<Machine> X = std::make_shared<Car>();
    (*X).run();
    std::shared_ptr<Machine::Parts> Y = std::make_shared<Car::Parts>();
    (*Y).get_wheels();
    return 0;
}

Я не нахожу другого кода с этой функциональностью. Единственное, чего мне не хватает - это возможности доступа к get_wheels напрямую с X. Например, давайте рассмотрим, что у меня есть Machine в моей программе. Тип машины у меня будет указываться динамически. Я хочу знать количество колес этой машины, но метод get_wheels должен быть внутри вложенного класса Parts. Чем ближе я решаю эту проблему, тем выше код, который дает мне Machine и Machine::Parts в качестве интерфейсов.

Ответы [ 2 ]

2 голосов
/ 16 января 2020

Простым решением было бы иметь часть-член вашей машины:

struct Car : Machine {
    struct Parts : Machine::Parts {
        int get_wheels() override {
            std::cout << "A car has 4 wheels." << std::endl;
            return 4;
        }

        std::string get_fuel_type() override {
            std::cout << "A car uses gasoline for fuel." << std::endl;
            return "gasoline";
        }
    } parts; // <---

    // or declare it as a separated member:
    // Parts parts;
};

Таким образом, вы можете вызывать функции-члены следующим образом:

Car car;
std::cout << car.parts.get_weels();
1 голос
/ 16 января 2020

Нет. В его нынешнем виде экземпляр Car не имеет ни экземпляров Car::Parts, ни каких-либо методов, которые его возвращают.

В тексте вокруг примера, как представляется, предполагается, что существует экземпляр, связанный с Machine::Parts с Machine каким-то образом, который волшебным образом становится Car::Parts в Car. Это может иметь место в некоторых других языках, но это не так в C ++.

Гораздо более сложной идеологией c будет иметь шаблон класса признаков, который специализируется Machine подклассами.

template <typename Machine>
struct MachineParts;

template <>
struct MachineParts<Car> {

    static int get_wheels() {
        std::cout << "A car has 4 wheels." << std::endl;
        return 4;
    }

    static std::string get_fuel_type() {
        std::cout << "A car uses gasoline for fuel." << std::endl;
        return "gasoline";
    }

};

template <>
struct MachineParts<Bicycle> {

    static int get_wheels() {
        std::cout << "A bike has 2 wheels." << std::endl;
        return 2;
    }

    static std::string get_fuel_type() {
        std::cout << "A bike uses muscles for fuel." << std::endl;
        return "muscles";
    }

};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...