使用特定成员变量值创建类型的类型
Create distinct type for class with specific member variable value
给定一个具有定义类型类的枚举的类,例如在以下示例中:
class Fruit {
public:
enum class FruitType {
AppleType = 0,
OrangeType = 1,
BananaType = 2,
};
Fruit(FruitType type) : type_(type) {}
FruitType fruit_type() const { return type_; }
private:
FruitType type_;
};
以及从中得出相同枚举的类别:
class DriedFruit : public Fruit {
public:
// Some Dried specific methods.
};
有可能以某种方式定义一个特定枚举值的水果和干果的不同类型:
class Apple // Fruit with FruitType = AppleType
class Orange // Fruit with FruitType = OrangeType
class Banana // Fruit with FruitType = BananaType
class DriedApple // DriedFruit with FruitType = AppleType
class DriedOrange // DriedFruit with FruitType = OrangeType
class DriedBanana // DriedFruit with FruitType = BananaType
使苹果,橙色和香蕉是不同的类型,三个类干燥,干果,干bana是不同的类型。
我的问题与如何在C 中定义同一类的不同类型有点相似,除了我想明确存储有关类中的enum成员变量的信息,并为所有不同的不同类型。
最有效的方法是什么?
编辑:主要用例如下 - 在我的应用中,某些方法只能期望苹果作为输入,或者只期望橙色作为输入,而许多不关心哪种水果的方法。
将水果传递到只期望苹果的方法感觉不安全/晦涩难懂,与此同时,有许多方法不在乎哪种类型是什么类型,因此拥有3种不同类型的方法也不是一个好选择。
主要工作流量如下:从某些输入参数中建立一个水果,然后将其传递并作为水果处理,然后在某个时候如果是苹果,请从水果转换为混凝土苹果类型,然后将其限制为从那时起的苹果。
最有效的方法是什么?
您可以使用非类型模板参数:
enum class FruitType {
AppleType = 0,
OrangeType = 1,
BananaType = 2,
};
template <FruitType F>
class Fruit {
public:
FruitType fruit_type() const { return F; }
};
using Apple = Fruit<FruitType::AppleType>;
using Banana = Fruit<FruitType::BananaType>;
您是否需要实际的基类取决于您。为某些FruitType
s。
这是您想做的吗?
enum class FruitType
{
AppleType = 0,
OrangeType = 1,
BananaType = 2,
};
class Fruit
{
public:
virtual FruitType fruit_type() const = 0;
};
class Apple: public Fruit
{
public:
FruitType fruit_type() const override { return FruitType::AppleType; }
};
class Orange : public Fruit
{
public:
FruitType fruit_type() const override { return FruitType::OrangeType; }
};
class Banana : public Fruit
{
public:
FruitType fruit_type() const override { return FruitType::BananaType; }
};
int main()
{
Fruit *somefruit = new Apple;
std::cout << "Is Apple? " << std::boolalpha << (somefruit->fruit_type() == FruitType::AppleType) << std::endl;
std::cout << "Is Orange? " << std::boolalpha << (somefruit->fruit_type() == FruitType::OrangeType) << std::endl;
std::cout << "Is Banana? " << std::boolalpha << (somefruit->fruit_type() == FruitType::BananaType) << std::endl;
return 0;
}
打印:
Is Apple? true
Is Orange? false
Is Banana? false
您的问题对要求很抽象。
尽管您的编辑澄清指导了一种方式
主要用例如下 - 在我的应用程序中,有些方法只期望苹果作为输入,或者只期望橙色作为输入,而许多不关心哪种水果的方法。
我正在考虑基于接口和 tag界面的完全不同的系统
(请参阅完整的实时演示)。
首先定义所有水果的常见接口:
// A basic interface common for all fruits
struct IFruit {
virtual ~IFruit() {}
virtual std::string category() const = 0;
virtual std::string common_name() const = 0;
virtual std::string botanical_name() const = 0;
};
// An overload for the output operator is just nifty
std::ostream& operator<<(std::ostream& os, const IFruit& fruit) {
os << "Category : " << fruit.category() << std::endl;
os << "Common Name : " << fruit.common_name() << std::endl;
os << "Botanical Name : " << fruit.botanical_name() << std::endl;
return os;
}
定义标签接口以区分您的特定类型(苹果,橙色):
// Tag interfaces to distinguish (not necessarily empty)
struct IApple : public IFruit {
virtual ~IApple() {}
};
struct IOrange : public IFruit {
virtual ~IOrange () {}
};
这些应暗中实现IFruit
接口。
现在您可以提供一个抽象基类,该类实现IFruit
接口。
该基类是 abractive 在某种意义上,构造函数函数隐藏在public
范围内,需要通过继承类构造函数来调用:
// Abstract base class implementation
template<class TagInterface>
class FruitBase : public TagInterface {
protected:
std::string category_;
std::string common_name_;
std::string botanical_name_;
FruitBase ( const std::string& category
, const std::string& common_name
, const std::string botanical_name)
: category_(category), common_name_(common_name)
, botanical_name_(botanical_name)
{}
public:
virtual ~FruitBase () {}
virtual std::string category() const { return category_; }
virtual std::string common_name() const { return common_name_; }
virtual std::string botanical_name() const { return botanical_name_; }
};
根据需要添加其他标签接口:
struct IDriedApple : public IApple {
virtual ~IDriedApple() {}
virtual int rest_humidity() const = 0;
};
现在,您可以使用相当狭窄的类固定来创建具体实现:
// Concrete apples
struct Boskop : public FruitBase<IApple> {
public:
Boskop() : FruitBase("Apples","Boskop","Malus domestica 'Belle de Boskoop'") {}
};
struct Braeburn : public FruitBase<IApple> {
public:
Braeburn() : FruitBase("Apples","Braeburn","Malus domestica") {}
};
// Concrete oranges
struct Valencia : public FruitBase<IOrange> {
public:
Valencia() : FruitBase("Oranges","Valencia","Citrus × sinensis") {}
};
struct Navel : public FruitBase<IOrange> {
public:
Navel() : FruitBase("Oranges","Navel","Citrus × sinensis") {}
};
这是我认为您的功能声明,专门用于服用 apples 或 oranges 仅:
void aFunctionThatTakesOnlyApples(IApple& anApple) {
std::cout << "This is an apple:" << std::endl;
std::cout << anApple;
}
void aFunctionThatTakesOnlyOranges(IOrange& anOrange) {
std::cout << "This is an orange:" << std::endl;
std::cout << anOrange << std::endl;
}
这是一个简单的模板函数,用于查询IFruit
的已知实例,用于实现特定的 tag接口: 模板 taginterface* querytaginterface(ifruit* frual){ 返回Dynamic_cast(水果); }
这就是您在行动中使用所有这些的方式:
int main() {
std::vector<std::unique_ptr<IFruit>> allFruits;
allFruits.push_back(std::make_unique<Boskop>());
allFruits.push_back(std::make_unique<Braeburn>());
allFruits.push_back(std::make_unique<Valencia>());
allFruits.push_back(std::make_unique<Navel>());
for(auto& fruit : allFruits) {
if(IApple* anApple = queryTagInterface<IApple>(fruit.get())) {
aFunctionThatTakesOnlyApples(*anApple);
}
if(IOrange* anOrange = queryTagInterface<IOrange>(fruit.get())) {
aFunctionThatTakesOnlyOranges(*anOrange);
}
std::cout << "-----------------------------------------------" << std::endl;
}
}
将水果传递到只期望苹果的方法感觉不安全/晦涩难懂,与此同时,有许多方法不在乎哪种类型是什么类型,因此拥有3种不同类型的方法也不是一个好选择。
我应该注意,我仍然不明白是什么使苹果和 oranges fuits 他们真的应该得到自己的类型。但是,这可能适用于多态类设计的不抽象隐喻,对具体类别的层次结构有用。
- 当我使用自定义类型创建动态数组时,即使使用字符串,它似乎也不起作用
- 根据模板的基本类型创建不同的模板类
- c++ 使用 CRTP 为变量模板中的每个类型创建纯虚拟重载
- C++使用模板为基元类型创建别名?
- 如何为基类通用类型创建向量以使用具体类型元素
- 如何使用基本类型创建C++多维名称数组
- 如何为多个C++类型创建编译时检查
- 从左到右从所有类型创建嵌套包
- 在抽象类中,可以使用抽象类A的类型创建一个静态字段
- 是否可以为缺少的模板成员类型创建默认类型?
- 将"sizeof"应用于不完整的类型(创建的类)无效
- 如何在Swig中为非基元数据类型创建包装器
- 如何在C++中为类型列表中的每个类型创建一个元素并将其添加到向量中
- 如何在MPI中从结构类型创建新的派生数据类型
- "错误:需要类型"创建新实例
- 如何从字符串中存储的类型创建实例
- 如何在编译时从类型创建静态字符串
- 如何使用特定类型创建 NULL
- 从文本文件导入的不同线类型创建变量
- 如何在Visual Studio 2013中为函数类型创建类型别名