【问题标题】:C++ vector of classes error类错误的 C++ 向量
【发布时间】:2013-08-03 04:03:19
【问题描述】:

我知道了

#include <vector>
using namespace std;

class A{
     protected:
         int test;
     public:
         void test(){} 
};
class B : public class A{
    public:
        void test2(){}
};

int main(){
     vector <A> new_vector;
     A a1;
     new_vector.push_back(a1);
     B b1;
     new_vector.push_back(b1);

     new_vector[0].test();
     //THE PROBLEM IS HOW DO I DO THIS:
     new_vector[1].test2();

}

逻辑上是可能的,但它给了我一个错误,我如何以正确的方式做到这一点?

在 python 中,我总是以一种非常简单的方式做类似的事情,在 c++ 中可能吗?

【问题讨论】:

  • 顺便说一句,您遇到了对象切片问题。
  • 请注意,这也没有多态性。

标签: c++ class function vector polymorphism


【解决方案1】:

您的问题是向量只包含A 对象的空间,无法在其中放置B

对于多态,您需要一个指针、引用或智能指针。为了帮助进行生命周期管理,建议使用后者。

std::vector<std::unique_ptr<A>> new_vector;
new_vector.emplace_back(new A());
new_vector.emplace_back(new B());

然后您可以在元素上使用dynamic_cast 来发现是否真的存在B 并调用B 特定成员。

但是,使用虚拟成员函数进行多态行为比dynamic_cast 高效得多。

【讨论】:

  • 我写了你所说的,我得到了这个:“无法解析符号'unique_ptr'”我目前正在使用eclipse和linux c++编译器
【解决方案2】:

您可以像 python 一样做到这一点,不将对象直接存储到向量中,而是使用指向实际对象本身的指针/引用。

#include <memory>
typedef std::vector<std::unique_ptr<A>> AVector;

在这种情况下允许多态性,您可以将指针推送到从 A 派生的任何内容。

在您尝试尝试的情况下,您尝试将圆形钉子安装到方孔中。 std::vector 实际上是一个简单的代码包装器,用于分配一大块内存成员 * sizeof(T)。

"unique_ptr" 是一个用于指针的 C++11 容器,它知道在它消失时将其删除。如果您没有 C++11/C++0x 支持,您可以使用指针或制作自己的“自动”指针包装器。

// Old-style pointer
typedef std::vector<A*> AVector;
AVector avec;

avec.push_back(new A);
avec.push_back(new B);
avec.push_back(new A);
avec.push_back(new B);

// now it's your responsibility to 'delete' these allocations when you remove them.
void discardAvec(size_t position) {
    A* ptr = avec[position];
    delete ptr;
    avec.erase(avec.begin() + position);
}

查看下面at ideone.com 的现场演示:

#include <iostream>
#include <memory>
#include <vector>

typedef std::vector<class A*> AVector;

class A
{
protected: // so B can access it.
    int m_i;
public:
    A(int i_) : m_i(i_)
    {
        std::cout << "CTor'd A(i) " << (void*)this
                  << " with " << m_i << std::endl;
    }
    A(int i_, bool) : m_i(i_)
    {
        std::cout << "CTor'd A(i, b) " << (void*)this
                  << " with " << m_i << std::endl;

    }

    virtual ~A()
    {
        std::cout << "DTor'd A " << (void*)this << " with " << m_i << std::endl;
    }
};

class B : public A
{
    int m_j;
public:
    B(int i_, int j_) : A(i_, true), m_j(j_)
    {
        std::cout << "CTor'd B(i, j) " << (void*)this
                  << " with " << m_i << ", " << m_j << std::endl;
    }

    virtual ~B()
    {
        std::cout << "DTor'd B " << (void*)this
                  << " with " << m_i << ", " << m_j << std::endl;
    }
};

int main()
{
    AVector avec;

    std::cout << "create A(1)" << std::endl;
    avec.push_back(new A(1)); // allocated an "A" on the heap.
    std::cout << "create B(2, 1)" << std::endl;
    avec.push_back(new B(2, 1)); // allocated a "B" on the heap.
    std::cout << "create B(2, 2)" << std::endl;
    avec.push_back(new B(2, 2));
    std::cout << "create A(3) " << std::endl;
    avec.push_back(new A(3));
    std::cout << "populated avec" << std::endl;

    A* ptr = avec[2]; // take the pointer of what is actually a B
    avec.erase(avec.begin() + 2); // remove it from the vector.
    std::cout << "removed entry 2 from the vector" << std::endl;
    // 'ptr' is still valid because it's an allocation, and C++ doesn't
    // garbage collect heap allocations. We have to 'delete' it ourselves.
    // Also note that because A and B have virtual destructors,
    // you will see both of them called.
    delete ptr;

    // Now watch what DOESN'T happen as we exit.
    // everything we CTOR'd that doesn't get DTORd is a leak.
    return 0;
}

【讨论】:

  • 我写了你所说的,我得到了这个:“无法解析符号'unique_ptr'”我目前正在使用eclipse和linux c++编译器
  • 它需要 #include &lt;memory&gt; 和 C++0x 或 C++11 支持。如果你没有这些,那么你可以只使用一个传统的指针,但是你必须确保你以后 delete 对象。参见例如我添加到答案中
  • 添加了一个完整的演示。
猜你喜欢
  • 2014-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-21
  • 2016-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多