C++ 类型转换替代虚拟方法

标签 c++ casting virtual

在 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 = truein_first_mode = false 都能正常工作。 所以,基本上,当您想编写适用于这两个类的代码时,您只需使用指向 BaseClass 的指针即可。

但是如果你已经给了数据缓冲区,填充了 TypeOne、TypeTwo、TypeThree 或 TypeFour 类型的数据,并且在运行时你知道该类型,它存储在 int 类型 中。问题是 TypeOne、TypeTwo、TypeThree 和 TypeFour 没有从一个基类继承。在我的例子中,实际上,它们是来自 3rd 方库的结构,它已经编译为 C 兼容库,所以我不能修改它。我想从上面的例子中得到类似 pointer 的东西,但是在确定什么 C++ 类型应该有这个 pointer 时出现了问题。

它有一个更优雅的类型转换替代方案来为这四种类型制作 C++ 类包装器(给出类似于上面的示例),并使 pointervoid * 和必要性

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/

相关文章:

c++ - gdb 前端与 vim 一起使用?

c++ - 为什么结构中的 QString 有时是一个坏指针?

c++抽象类在非纯虚函数中使用纯虚函数

c - 在 C 中使用 qsort/casting

c++ - 虚拟方法不虚拟

c++ - 免费的 Pascal/C++ 项目在 cout::sentry 中崩溃

mysql - MySQL 5.5:当我对BIT数据类型使用“CONV”时,为什么有任何基础工作

c# - 为什么 C# 中的字节减法需要强制转换?

c++ - 虚拟基类上的虚拟方法

c++ - 虚拟方法返回代表派生对象类型的枚举 - 可以吗(就设计而言)?