假设我有一个模板化的抽象
Fish
类,其中有两个模板化的子级:
template<typename T>
class Fish {
public:
virtual ~Fish() = default;
// Pure virtual method to make Fish an abstract class
virtual void swim() const = 0;
// A common method for all fish
void breathe() const {
std::cout << "Fish is breathing." << std::endl;
}
};
// Templated Salmon class (child of Fish)
template<typename T>
class Salmon : public Fish<T> {
public:
void swim() const override {
std::cout << "Salmon is swimming with value = " << T << std::endl;
}
};
// Templated Goldfish class (child of Fish)
template<typename T>
class Goldfish : public Fish<T> {
public:
void swim() const override {
std::cout << "Goldfish is swimming with value = " << T << std::endl;
}
};
我想制作一个非模板化的 Aquarium 类,它存储 Fish 对象的向量并具有
void addFish(Fish)
和 Fish removeFish()
函数。
我该怎么做?
类似于这个占位符代码
// Aquarium class (non-templated)
class Aquarium {
private:
SomeType?? fishTank; // Store fish objects
public:
// Add fish to the aquarium (now templated to handle any type of Fish<T>)
template<typename T>
void addFish(SomeType??? fish){...}
template<typename T>
SomeType??? removeFish(){...}
// Method to make all fish swim
void makeFishSwim() {
for (auto& fish : fishTank) {
fish->swim();
}
}
};
int main() {
Aquarium aquarium;
// Create fish objects
auto salmon = std::make_shared<Salmon<int>>();
auto goldfish = std::make_shared<Goldfish<int>>();
// Add fish to the aquarium doing something like this
aquarium.addFish(salmon);
aquarium.addFish(goldfish);
// Make all fish swim
aquarium.makeFishSwim();
return 0;
}
我认为这个例子涵盖了您正在寻找的内容:
参见:https://onlinegdb.com/mzbURVQVV
#include <iostream>
#include <memory>
#include <string>
#include <vector>
// Begin with an abstract baseclass modeling
// what a fish can do
class FishItf
{
public:
virtual void Swim() = 0;
virtual ~FishItf() = default;
};
// Default reusable implmentation of the fish interface
template<typename FishType>
class FishItfImpl : public FishItf
{
public:
void Swim() override
{
std::string name = typeid(FishType).name();
auto pos = name.find_first_not_of("0123456789");
name = name.substr(pos);
// typeid allows you to get a unique name for the type (not quite the original class name)
std::cout << name << " is swimming\n";
}
};
// A salmon with default fish implementation
class Salmon :
public FishItfImpl<Salmon>
{
};
// And a bad ass brass can sing too
class BadAssBrass :
public FishItfImpl<BadAssBrass>
{
public:
void Sing()
{
std::cout << "Take me to the river...\n";
}
};
int main()
{
Salmon salmon;
salmon.Swim();
BadAssBrass brass;
brass.Swim();
brass.Sing();
// But you can now also make a vector of FishItf
std::vector<std::unique_ptr<FishItf>> fishes;
fishes.emplace_back(std::make_unique<Salmon>());
fishes.emplace_back(std::make_unique<BadAssBrass>());
std::cout << "\n\nLet all the fishes swim : \n";
for(const auto& fish : fishes)
{
fish->Swim();
}
};