2014-09-02 3 views
1

У меня есть два классаC++ Реферирование внутри полиморфного объекта

class A { C* c; } 

class B { D* d; } 

и найти мне нужно построить зЬй :: вектор, элементы которого являются либо А, либо В (с последовательностью решили во время выполнения. Так что я построил Полиморфный

class Poly { 
    int oType; 
    void* oPtr; 
} 

, а также конструктор

Poly::Poly(int type) 
{ 
    if (type == 1) oPtr = new (A*) oPtr(); 
    if (type == 2) oPtr = new (B*) oPtr(); 
    oType = type; 
} 

наряду с аналогичным структурированы деструктор. В настоящее время

std::vector<Poly*> test; 

работает. Однако у меня возникают проблемы с доступом к подобъектам.

Я попытался

if (test->oType == 1) test->oPtr->a; 

if (test->oType == 1) test->(A*)oPtr->a; 

if (test->oType == 1) (A*)(test->oPtr)->a; 

все дает мне ошибку компилятора:

«пустота *» не является указатель на объект типа

Как убедить компилятор, что OK для ссылки a, если я знаю, что тип oPtr - A *?

+2

'если (тест-> oType == 1) ((A *) тест-> OPTR) -> c' – nwp

+2

Почему вы используете' 'вектор и' 'вектор ? – nwp

+4

В C++ полиморфизм обычно выражается путем наследования от общего базового класса. Затем обычно пытаются решить проблему выбора типа объекта, используя виртуальные методы, а не традиционные конструкции «if/then». – Galik

ответ

2

How do I convince the compiler that it's OK to reference a, if I know that the type of oPtr is A*?

Строго я считаю, что ответ на этот вопрос: ((A*)(test->oPtr))->a. Лучший способ сделать это в C++ использует оператор литья: static_cast<A*>(test->oPtr)->a

HOWEVER Как правило, эта проблема не рассматривается в C++. Таким образом, я обеспечил более обычный подход, который вы можете найти полезным:

class Poly 
{ 
public: 
    virtual ~Poly() {} 
    virtual void do_something() = 0; // each sub-type has its own version of this 
}; 

class A: public Poly 
{ 
public: 
    void do_something() /* override */ // c++11 only 
    { 
     std::cout << "Doing something A specific\n"; 
    } 
}; 

class B: public Poly 
{ 
public: 
    void do_something() /* override */ // c++11 only 
    { 
     std::cout << "Doing something B specific\n"; 
    } 
}; 

int main() 
{ 
    std::vector<Poly*> polys; 

    // create data structure 
    polys.push_back(new A); 
    polys.push_back(new A); 
    polys.push_back(new B); 
    polys.push_back(new A); 

    // use objects polymorphically 
    for(size_t i = 0; i < polys.size(); ++i) 
     polys[i]->do_something(); 

    // clean up memory (consider using 'smart pointers') 
    for(size_t i = 0; i < polys.size(); ++i) 
     delete polys[i]; 
} 
+0

Не будет 'static_cast (test-> oPtr) -> a' лучше? – matsjoyce

+0

@matsjoyce Да, вы правы. Я добавлю это. – Galik

0

Как и другие упоминали, полиморфный способ заключается в использовании виртуальных функций.

Вот реализация с использованием интеллектуальных указателей. Класс creator отвечает за создание объекта Poly, о котором мы просим. Это изолирует создание до одного класса.

Обратите внимание, что есть более сложные способы сделать это. Цель здесь - показать, более или менее, как это будет сделано с использованием C++.

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

class Poly 
{ 
    public: 
     virtual void Test() = 0; 
}; 

typedef std::unique_ptr<Poly> PolyPtr; 

class A : public Poly 
{ 
    public: 
     void Test() { std::cout << "Test for A" << "\n"; } 
}; 

class B : public Poly 
{ 
    public: 
     void Test() { std::cout << "Test for B" << "\n"; } 
}; 

class PolyCreator 
{ 
    public: 
     PolyPtr CreatePolyObject(int oType) 
     { 
      switch(oType) 
      { 
       case 1: 
        return PolyPtr(new A()); 
       case 2: 
        return PolyPtr(new B()); 
      } 
      throw "Could not find type in list"; 
     } 
}; 

int main() 
{ 
    PolyCreator pCreator; 
    std::vector<PolyPtr> PolyPtrVect; 

    // create objects 
    PolyPtrVect.push_back(pCreator.CreatePolyObject(1)); 
    PolyPtrVect.push_back(pCreator.CreatePolyObject(2)); 

    // call Test functions for each 
    std::vector<PolyPtr>::iterator it = PolyPtrVect.begin(); 
    while (it != PolyPtrVect.end()) 
    { 
     (*it)->Test(); 
     ++it; 
    } 
} 

Выход:

Test for A 
Test for B 

Примечание

  1. Существует только один if() утверждение, что выделяют в класс PolyCreator.
  2. Утечка памяти из-за использования std::unique_ptr.
  3. Poly является абстрактным классом. Все производные классы должны реализовывать функцию Test.
Смежные вопросы