【问题标题】:Working with a void pointer使用 void 指针
【发布时间】:2012-11-28 11:54:01
【问题描述】:

鉴于以下情况,我的数据可能基于某些条件属于不同类型。

class myClass {
public:
    myclass() {
        if (condition1) {
          bool boolValue = false;
          data = boolValue;
        } else if (condition2) {
          int intValue = 0;
          data = intValue;
        } else if (condition3) {
          unsigned int unsignedIntValue = 0;
          data = unsignedIntValue;
        } else if (condition4) {
          long longValue = 0;
          data = longValue;
        } else if (condition5) {
          double doubleValue = 0.0;
          data = doubleValue;
        } else if (condition6) {
          float floatValue = 0.0;
          data = floatValue;
        } else if (condition7) {
          char *buffer = new char[10];
          data = buffer;
        }
    }

    void* getData() const { return data; }

private:
    void *data;
}

碰巧我的 void 指针指向的值严格在每个语句中。因此,使用 getData() 返回的内容可能无效。如果我确实得到了数据,那只是因为我指向的内存位置还没有被覆盖。

我想出的解决方案是这样的:

class myClass {
public:
    myclass() {
        if (condition1) {
          boolValue = false;
          data = boolValue;
        } else if (condition2) {
          intValue = 0;
          data = intValue;
        } else if (condition3) {
          unsignedIntValue = 0;
          data = unsignedIntValue;
        } else if (condition4) {
          longValue = 0;
          data = longValue;
        } else if (condition5) {
          doubleValue = 0.0;
          data = doubleValue;
        } else if (condition6) {
          floatValue = 0.0;
          data = floatValue;
        } else if (condition7) {
          buffer = new char[10];
          data = buffer;
        }
    }

    void* getData() const { return data; }

private:
    void *data;
    bool boolValue;
    int intValue;
    unsigned int unsignedIntValue;
    long longValue;
    double doubleValue;
    float floatValue;
    char *buffer;
}


我在想必须有一种更优雅的方式来做到这一点。有什么建议吗?

【问题讨论】:

  • 你看过boost::variant吗?
  • 你应该使用 Python。使用像 C++ 这样具有严格类型系统的语言只是为了绕过类型系统而使用错误的工具。不同的类型是不同的类型是有充分理由的。
  • 可能有更好的方法可以做到这一点,但如果没有更多的上下文,就不可能说出那可能是什么。从您所展示的内容来看, void 指针看起来完全没有必要,可以将其删除。我认为它是有目的的,而这个目的决定了哪种实现可以更优雅地解决问题
  • 糟糕,为 boost::variant +1。你不敢为了拥有一个 getData() 函数而将类型转换为 void:-P 向天空挥拳,看着你失望。编辑:或者...使用模板类:-)?
  • 即使您不喜欢模板或 boost,当然您也可以拥有一个顶级 Data 类并传递指向该实例的指针,然后使用 RTTI 和 dynamic_cast 尝试将其转换为IntDataBoolData 子类等。

标签: c++ void-pointers


【解决方案1】:

您可以使用联合在内存中保存一些位,然后使用指针转换从联合中获取值:

#include<iostream>
using namespace std;

class myClass {
public:
    myClass(char *str){
        data.str = str;
    }
    myClass(double d){
        data.d = d;
    }
    myClass(float f){
        data.f = f;
    }

    void *getData() { return (void*)&data; }
private:
    union {
        double d;
        float f;
        char *str;
    } data;
};

int main(){
    myClass c(2.0);
    cout << *(double*)c.getData() << endl;

    myClass f(3.0f);
    cout << *(float*)f.getData() << endl;

    myClass s("test");
    cout << *(char**)s.getData() << endl;

    system("pause");
}

/* prints
2
3
test
*/

【讨论】:

    【解决方案2】:

    如果创建对象后不需要更改数据类型,则可以使用模板类:

    template <typename T>
    class myBaseClass {
    public:
        // Declare common functions here.
        T getData()
        { return data; }
    
    protected:
        T data;
    
    protected:
        // Disallow constructing instances of this class outside the child classes.
        myBaseClass(T val) : data(val) { }
    };
    
    template <typename T>
    class myClass: public myBaseClass<T> {
    public:
        myClass() : myBaseClass<T>(0) { }
    };
    

    然后你专攻char*

    template <>
    class myClass<char*>: public myBaseClass<char*> {
    public:
        myClass() : myBaseClass(new char[10]) { }
    };
    

    然后你创建这样的实例:

    myClass<int> a;
    myClass<float> b;
    myClass<char*> c;
    // etc.
    int i = a.getData();
    float f = b.getData();
    char* str = c.getData();
    

    【讨论】:

    • 有效,但仍然有点过于复杂。
    • @BartekBanachewicz 是的,虽然性能比运行时类型切换要好,当然它是类型安全的。
    猜你喜欢
    • 2014-05-30
    • 2013-12-18
    • 2019-05-24
    • 2020-04-01
    • 2015-01-01
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 2012-02-07
    相关资源
    最近更新 更多