2013-08-03 3 views
0

Я получил этоC++ вектор классов ошибок

#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++?

+3

Кстати, Вы имеете вопрос срез объекта. – billz

+0

На этой ноте ничего не может быть и полиморфным. – WhozCraig

ответ

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.

+0

Я написал то, что вы сказали, и у меня есть это: «Symbol« unique_ptr »не может быть разрешен» Я в настоящее время использую компилятор eclipse и linux C++ – newtonis

0

Вы можете сделать это так же, как это делает 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; 
} 
+0

Я написал то, что вы сказали, и у меня есть это: «Symbol 'unique_ptr' не удалось решить. «В настоящее время я использую компилятор eclipse и linux C++. – newtonis

+0

Он нуждается в' #include ' и поддержке C++ 0x или C++ 11. Если у вас их нет, то вместо этого вы можете использовать только традиционный указатель, но тогда вы должны убедиться, что вы «удаляете» объекты позже. См. Я добавил к ответу – kfsone

+0

Добавлена ​​полная флэш-демонстрация. – kfsone