2012-09-07 34 views
1

如何使用支持不同类型项目的数组实现堆栈。 例如它应该在字符,整数,浮动和双打上运行。使用数组实现堆栈以支持不同数据类型的项目

我已经使用void指针实现了它。下面是C实现:

void push(void** stack, int* top, void* data, size_t size) 
{ 
    unsigned i; 
    ++*top; 

    stack[*top] = malloc(size); 

    for(i = 0; i < size; ++i) 
      ((char*)stack[*top])[i] = ((char*)data)[i]; 

} 

int main() 
{ 
    void* stack[10]; 
    int top = -1, data = 10; 
    char ch = 'a'; 

    push(stack, &top, (void*)&data, sizeof(int)); 

    push(stack, &top, (void*)&ch, sizeof(char));   

    printf("%d ", *(int*)stack[0]); 
    printf("%c ", *(char*)stack[1]); 

    return 0; 
} 

我的代码works fine

上述实现的问题是必须事先知道数据的类型。

是否存在一种方法来实现它,而不知道有关要操作的数据类型的先前信息[我知道这在C中是不可能的,我们可以用C++来做,如果是,如何? ]?

+1

[RTTI](http://en.wikipedia.org/wiki/Run-time_type_information)...虽然在C++中通常容器是使用类型参数的模板。请注意['std :: stack'](http://en.cppreference.com/w/cpp/container/stack)。 – oldrinb

+0

是的,容器是模板。但是AFAIK,他们一次只支持一种类型。 –

+0

这是C或C++吗?因为每种语言的解决方案都不相同。 –

回答

0

如果我了解您的要求,您可以使用boost::any在C++中实现此目的。

#include <boost/any.hpp> 
#include <vector> 

class AnyStack { 
    std::vector<boost::any> vec; 
public: 
    template <class T> void push (const T &e) { 
     boost::any v = e; 
     vec.push_back(v); 
    } 
    class Proxy { 
     friend class AnyStack; 
     std::vector<boost::any> &vec; 
     Proxy(std::vector<boost::any> &v) : vec(v) {} 
    public: 
     template <typename T> operator T() { 
      boost::any v = vec.back(); 
      vec.pop_back(); 
      return boost::any_cast<T>(v); 
     } 
    }; 
    Proxy pop() { return Proxy(vec); } 
    boost::any top() { return vec.back(); } 
}; 

正如其他人所建议的,您可以使用RTTI来确定堆栈中物品的类型。下面的示例演示了执行此操作的输出例程。

#include <iostream> 
#include <string> 

std::ostream & operator << (std::ostream &os, const boost::any &a) { 
    if (a.type() == typeid(char)) { 
     return os << boost::any_cast<char>(a); 
    } 
    if (a.type() == typeid(int)) { 
     return os << boost::any_cast<int>(a); 
    } 
    if (a.type() == typeid(float)) { 
     return os << boost::any_cast<float>(a); 
    } 
    if (a.type() == typeid(double)) { 
     return os << boost::any_cast<double>(a); 
    } 
    if (a.type() == typeid(std::string)) { 
     return os << boost::any_cast<std::string>(a); 
    } 
} 

int main() { 
    AnyStack a; 
    a.push(3); 
    std::cout << a.top() << std::endl; 
    a.push(std::string("hello")); 
    std::cout << a.top() << std::endl; 
    return 0; 
} 
3

它可以在C.首先要做你需要描述所含类型的枚举

typedef enum {TYPE_INT, TYPE_CHAR, TYPE_STRING, ... } contained_type_t; 

然后把一切都放在一个结构

typedef struct { 
    contained_type_t contained_type; 
    union { 
    int int_value; 
    char char_value; 
    void* pointer_value; 
    ... and so on ... 
    } data; 
}; 

你可以看看在GObject模型和其用途为GLib,执行通用列表可混合类型很有意思。

+0

这种方法被广泛使用。虽然它有一个限制,即工会的所有成员都不能拥有委托人/代理人。另外,应该提前知道支持类型的完整列表。 –

+0

@KirillKobelev如果c-tors和d-tors,这是C++,所以现在的标准是C++ 11,其中union的成员可以有c-tors,d-tors。 – ForEveR

+0

@KirillKobelev有这种方法,但是GObject模型没有这个限制,但是对于一个简单的栈实现来说有点矫枉过正 – Kwariz