需要派生类的动态强制转换:寻找替代方法
A need for dynamic cast of a derived class: looking for an alternative approach
我以这种简单的形式提出我的问题:
class animal {
public:
animal() {
_name="animal";
}
virtual void makenoise(){
cout<<_name<<endl;
}
string get_name(){
return _name;
}
protected:
string _name;
};
class cat : public animal {
public:
cat() {
this->_name="cat";
}
};
class dog : public animal {
public:
dog() {
this->_name = "dog";
}
};
我想将所有动物类型一起存储在一个容器中,例如:
vector<animal*> container;
barnyard.push_back(new animal());
barnyard.push_back(new dog());
barnyard.push_back(new cat());
在我的代码中的某个时刻,我需要将狗对象转换为猫对象。我从这种转换中需要的只是设置一个新的狗对象,并将其替换为与猫对应项所在的相同索引号。据我了解,在这种情况下dynamic_cast
不起作用,并且基于C++转换为派生类,有人提到这种转换不是一个好的做法。由于我的模型中的猫和狗具有不同的行为属性,我不想将它们的定义放入动物模型中。另一方面,将它们分别存储在不同的向量中将难以处理。有什么建议吗?
你说:
我需要将狗对象转换为猫对象。
但随后:
我从这种转换中需要的只是设置一个新的狗对象,并将其替换为与猫对应项所在的相同索引号。
您需要转换或替换它吗?这是一个完全不同的操作。
要转换,您需要设置一个函数,该函数将带走一只狗并返回一只猫:
auto convertDogToCat(Dog const& dog) -> Cat {
auto cat = Cat{};
// fill cat's member using dog's values...
return cat;
}
但是要替换只是用一个新的重新分配:
// v--- a cat is currently there
barnyard[ii] = new Dog{};
// ^--- we replace the old pointer
// with one that points to a dog.
但这会产生内存泄漏,要消除泄漏,只需使用std::unique_ptr
:
#include <memory> // for std::unique_ptr
// The base class need a virtual destructor
class animal {
public:
virtual ~animal() = default;
// other members...
};
std::vector<std::unique_ptr<animal>> barnyard;
barnyard.emplace_back(std::make_unique<animal>());
barnyard.emplace_back(std::make_unique<dog>());
barnyard.emplace_back(std::make_unique<cat>());
barnyard[ii] = std::make_unique<Dog>();
这是一种替代方法。不使用 OOP 或动态调度,但为您的样品提供相同的功能。也快得多,因为不需要动态内存来分配/释放,动物是单个字节。
enum struct eAnimalKind : uint8_t
{
Generic = 0,
Cat = 1,
Dog = 2,
};
string get_name( eAnimalKind k )
{
static const std::array<string, 3> s_names =
{
"animal"s, "cat"s, "dog"s
};
return s_names[ (uint8_t)k ];
}
void makenoise( eAnimalKind k )
{
cout << get_name( k ) << endl;
}
如果您的类保留的状态多于某个类型,请使用一个具有该枚举的类作为成员。
如果某些动物使用自定义字段/属性集,它会变得棘手,但仍然可能,嵌套结构用于特定于物种的状态,以及这些结构的 std::variantclass animal
以跟踪物种并保留数据。在这种情况下,您不再需要enum eAnimalKind
,std::variant 已经跟踪它包含的类型。
经典C++ OOP 需要动态内存。派生类通常具有不同的大小,您不能将它们保存在单个向量中,您只能保留指针,并且在运行时访问每个元素时会遇到 RAM 延迟。
如果您的动物又大又复杂,即兆字节的 RAM 和昂贵的方法,那很好。但是,如果您的动物很小,包含几个字符串/数字,并且您有很多字符串/数字,则RAM延迟将破坏OOP方法的性能。
- 防止主数据类型C++的隐式转换
- 模板参数替换失败,并且未完成隐式转换
- 努力将整数转换为链表。不知道我在这里做错了什么
- HEX值到wchar_t字符(UTF-8)的转换
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将 Qvector<uint8_t> 转换为 QString
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- QT在错误的班级中寻找空位
- 在c++中使用nlohmann从类到json的转换
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- 复制列表初始化的隐式转换的等级是多少
- 正在将指针转换为范围
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 需要派生类的动态强制转换:寻找替代方法
- 寻找Boost转换迭代器的复合特征模式
- 从C转换到C++:寻找基元类型的安全类