代码之家  ›  专栏  ›  技术社区  ›  Tim

在C++中维护任何对象类型的引用?

  •  9
  • Tim  · 技术社区  · 16 年前

    Object data

    我找不到类似的,惯用的C++方式来存储任何类型的对象。 void 指针;同样的事情对于C++来说是很有用的,但是在构建一个实例时,我遇到了一些问题。 std::string 并尝试将其存储到列表/树中(关于来自的无效强制转换的内容) std::string& void* ). 有这样的方法吗?C++是否具有java对象的等价性(或者Objtovi-C的NSObjor)?

    附加问题:如果没有,我需要继续使用void指针,那么存储一个空指针的“正确”方法是什么 字符串 static_cast<char*>(str.c_str())

    6 回复  |  直到 16 年前
        1
  •  12
  •   Charles Salvia    16 年前

    C++没有一个java对象继承所有对象的基类对象。通常的方法是使用 templates . 标准C++库中的所有容器都使用这种方法。

    Object ,因此任何类都可以插入到接受 . 然而,C++模板是编译时构造,它指示编译器实际上为每个类型使用不同的类。例如,如果您有:

    template <typename T>
    class MyContainer { ... };
    

    然后可以创建一个 MyContainer 这需要 std::string 对象和另一个需要 int s

    MyContainer<std::string> stringContainer;
    stringContainer.insert("Blah");
    
    MyContainer<int> intContainer;
    intContainer.insert(3342);
    
        2
  •  9
  •   parti3an    16 年前

    您可以查看boost::任意类。它是类型安全的,您可以将其放入标准集合中,并且不需要与任何库链接,该类在头文件中实现。

    它允许您编写如下代码:

    #include <list>
    #include <boost/any.hpp>
    
    typedef std::list<boost::any> collection_type;
    
    void foo()
    {
        collection_type coll;
        coll.push_back(boost::any(10));
        coll.push_back(boost::any("test"));
        coll.push_back(boost::any(1.1));
    }
    

    完整文档如下所示: http://www.boost.org/doc/libs/1_40_0/doc/html/any.html

        3
  •  3
  •   lhahne    16 年前

    你要找的是模板。它们允许您创建类和函数,允许您获取任何数据类型。

        4
  •  2
  •   Zhro    10 年前

    是静态的方法来实现这一点。它们的行为类似于Java和C#泛型,但100%是静态的(编译时)。如果您不需要在同一个容器中存储不同类型的对象,请使用此选项(其他答案对此描述得非常好)。

    基类上的指针 . 当然,你必须定义你自己的对象层次结构,因为C++中没有这样的“对象”类:

    #include <list>
    
    class Animal {
    public:
       virtual ~Animal() {}
    };
    
    class Dog : public Animal {
    public:
       virtual ~Dog() {}
    };
    
    class Cat : public Animal {
    public:
       virtual ~Cat() {}
    };
    
    int main() {
        std::list<Animal*> l;
        l.push_back(new Dog);
        l.push_back(new Cat);
    
        for (std::list<Animal*>::iterator i = l.begin(); i!= l.end(); ++i)
            delete *i;
    
        l.clear();
    
        return 0;
    }
    

    智能指针更容易使用。以身作则 boost::smart_ptr :

    std::list< boost::smart_ptr<Animal> > List;
    List.push_back(boost::smart_ptr<Animal>(new Dog));
    List.push_back(boost::smart_ptr<Animal>(new Cat));
    List.clear(); // automatically call delete on each stored pointer
    
        5
  •  1
  •   David Brown    16 年前

    你应该可以投一个 void* 变成 string* 使用标准C样式转换。请记住,引用在使用时不会被视为指针,而是被视为普通对象。因此,如果要通过引用将值传递给函数,仍然必须取消引用以获取其地址。

    然而,正如其他人所说,更好的方法是使用模板

        6
  •  1
  •   David Thornley    16 年前
    static_cast<char*>(str.c_str())
    

    我觉得很奇怪。 str.c_str() const char * char * 你通常会使用 const_cast<char *>(str.c_str()) . 但这样做不好,因为你会干预一个系统的内部 string . 你确定没有收到警告吗?

    你应该能够使用 static_cast<void *>(&str) std::string& 是对 一串 ,而不是指向的指针,因此错误消息是正确的。我不知道的是你是如何得到一个引用而不是一个指针的。)

    是的,这是冗长的。这是有意的。在C++程序中,铸造通常被认为是一种难闻的气味,Stroustrup希望铸件易于找到。正如在其他答案中所讨论的,构建任意基类型的数据结构的正确方法是使用模板,而不是强制转换和指针。