Как создать шаблонный тип класса, который может быть заменен на подклассы и затем вызываться в общем? - PullRequest
0 голосов
/ 02 мая 2019

У меня есть 10 типов монет: BTC, ETH, Shift и т. Д. Для этого у меня есть суперкласс «Монета» и подклассы для каждой из этих монет.Затем у меня есть указатель на тип «Coin», так что я могу вызывать каждый из подклассов независимо от того, какой они подтип.

Проблема в том, что я знаю, как это сделать только в Java, а не в C ++,Мне трудно искать правильные термины, потому что я не знаю, что искать, кроме «дженериков».Я хочу что-то вроде этого:

// Superclass
class Coin {
public:
    virtual void handleCoin();
};


// Subclass
class BTC: public Coin {
    void handleCoin();
}

BTC::BTC() = default;
BTC::~BTC() = default;

BTC::handleCoin() {
    std::cout << "handling BTC" << std::endl;
}


// Subclass
class ETH: public Coin {
    void handleCoin();
}

ETH::ETH() = default;
ETH::~ETH() = default;

ETH::handleCoin() {
    std::cout << "handling ETH" << std::endl;
}


// Execute
int main() {
    Coin* coin;
    coin = BTC();
    coin.handleCoin();
    coin = ETH();
    coin.handleCoin();
    return 0;
}

Я хочу это напечатать:

handling BTC
handling ETH

Я знаю, что мне нужно работать с шаблонами, но я не могу найти конкретный пример этогоконкретный случай.

Кроме того, мои конструкторы не принимают аргументы, поэтому я предполагаю, что объявление моего шаблона будет выглядеть примерно так:

template<>

Все же все примеры, которые я вижу, работают с

template<typename T>

, а затем использовать тип T в качестве аргументов функции, таких как вызов

max<float, float>
max<double, double>

Но это не то, что я ищу.Есть ли способ перевести этот пример выше на рабочий код C ++?

1 Ответ

2 голосов
/ 02 мая 2019

Из размещенного кода я не вижу необходимости в шаблонах, виртуальные методы работают без шаблонов. Для исправления кода в основном вам нужно использовать указатели / ссылки, а также иметь виртуальный деструктор.

class Coin {
public:
    virtual void handleCoin();
    virtual ~Coin()=default;
};
class BTC: public Coin {
public:
    BTC::BTC() = default;
    //Destructor of a derived class is automatically virtual if the base class's one is.
    void handleCoin();
}

// Subclass
class ETH: public Coin {
    void handleCoin();
    ETH::ETH() = default;
    //Still virtual even if you specify otherwise
    ETH::~ETH() = default;
}
int main() {
    Coin* coin;
    coin = new BTC();//Returns BTC*   <--pointer

    coin->handleCoin();
    delete coin;//Calls Coin::~Coin() -> thus the need for virtual so BTC::~BTC is called instead.
    coin = new ETH();
    coin->handleCoin();
    delete coin;//Same, calls ETH::~ETH()
    return 0;
}

Ручное управление памятью подвержено ошибкам, в C ++ 11 есть лучший подход, который настоятельно рекомендуется:

int main() {
    std::unique_ptr<Coin> coin;//Hides the pointer, but still has pointer-like semantics
    coin = std::make_unique<BTC>();
    coin->handleCoin();
    //Automatically frees old memory
    coin = std::make_unique<BTC>();
    coin->handleCoin();
    //Calls unique ptr's dtor because coin is local variable, which again frees the memory correctly.
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...