在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 type
中的类型。问题是TypeOne,TypeTwo,TypeThree和TypeFour没有从一个基类继承。在我的情况下,实际上,它们是来自第三方库的结构,它已经编译了C兼容库,所以我无法修改它。我希望从上面的示例中获得类似pointer
的内容,但是在确定C ++类型应该具有此pointer
时会出现问题。
它有一个更优雅的类型转换替代方法,可以为这四种类型制作C ++类包装器(它提供类似于上面的示例),并使pointer
成为void *
,并且需要< / p>
if (type == 1) {
TypeOne *type_one_pointer = static_cast<TypeOne*>(pointer);
// do something
} else if (type == 2) {
/* ... */
}
每次我使用pointer
?
答案 0 :(得分:2)
如果类不相关,则可以将它们存储在std::variant
中(如果编译器不符合C ++ 17,则使用Boost.Variant)并使用访问者访问该值。这比模板更灵活,因为它允许您在变体类型中包含具有不同接口的类型。
例如(我没有编译此代码):
#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);
}
}
答案 1 :(得分:0)
感谢@ForEveR,我找到了解决方案。我需要使用模板。
这意味着如果在上面的示例中,FirstClass和SecondClass没有BaseClass,则可以这样做:
{{1}}