在 C++ 中,您可以使用虚方法让以下代码按预期工作:
#include <iostream>
#include <string>
class BaseClass {
public:
virtual std::string class_name() const { return "Base Class"; }
};
class FirstClass : public BaseClass {
int value = 1;
public:
std::string class_name() const { return "FirstClass"; }
};
class SecondClass : public BaseClass {
long long value = -1;
public:
std::string class_name() const { return "SecondClass"; }
};
int main() {
const int array_size = 5;
const bool in_first_mode = true;
void *data;
int sample_size;
if (in_first_mode) {
data = new FirstClass[array_size];
sample_size = sizeof(FirstClass);
} else {
data = new SecondClass[array_size];
sample_size = sizeof(SecondClass);
}
// this is class-independent code
for (int index = 0; index < array_size; ++index) {
BaseClass *pointer = static_cast<BaseClass*>(data + index * sample_size);
std::cout << pointer->class_name() << std::endl;
}
return 0;
}
这对 in_first_mode = true
和 in_first_mode = false
都能正常工作。
所以,基本上,当您想编写适用于这两个类的代码时,您只需使用指向 BaseClass 的指针即可。
但是如果你已经给了数据缓冲区,填充了 TypeOne、TypeTwo、TypeThree 或 TypeFour 类型的数据,并且在运行时你知道该类型,它存储在 int 类型
中。问题是 TypeOne、TypeTwo、TypeThree 和 TypeFour 没有从一个基类继承。在我的例子中,实际上,它们是来自 3rd 方库的结构,它已经编译为 C 兼容库,所以我不能修改它。我想从上面的例子中得到类似 pointer
的东西,但是在确定什么 C++ 类型应该有这个 pointer
时出现了问题。
它有一个更优雅的类型转换替代方案来为这四种类型制作 C++ 类包装器(给出类似于上面的示例),并使 pointer
为 void *
和必要性
if (type == 1) {
TypeOne *type_one_pointer = static_cast<TypeOne*>(pointer);
// do something
} else if (type == 2) {
/* ... */
}
每次我使用指针
?
最佳答案
如果这些类不相关,您可以将它们存储在 std::variant
中(或者如果您的编译器不兼容 C++17,则使用 Boost.Variant)并通过访问者访问该值.这比模板更灵活,因为它允许您在变体类型中包含具有不同接口(interface)的类型。
例如(我没有编译这段代码):
#include <iostream>
#include <string>
#include <variant>
#include <vector>
struct TypeOne {
std::string class_name() const { return "Type one"; }
};
struct TypeTwo {
int value = 1;
std::string class_name() const { return "Type two"; }
};
struct TypeThree {
long long value = -1;
// note the different function signature
static std::string class_name() { return "Type three"; }
};
struct TypeFour {
std::string getMyClassName() const { return "Type four"; }
};
struct Visitor {
template <class T>
void operator ()(T&& value) const {
std::cout << value.class_name() << std::endl;
}
// special case
void operator ()(const TypeFour& value) const {
std::cout << value.getMyClassName() << std::endl;
}
};
int main() {
typedef std::variant<TypeOne, TypeTwo, TypeThree, TypeFour> Variant;
std::vector<Variant> values;
values.emplace_back(TypeOne{});
values.emplace_back(TypeTwo{});
values.emplace_back(TypeThree{});
values.emplace_back(TypeFour{});
for (const auto& var : values) {
std::visit(Visitor{}, var);
}
}
关于C++ 类型转换替代虚拟方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42343279/