2015-01-27 5 views
0

У меня проблема с доступом к объекту, который является переменной класса. Наследование и отношения выглядят следующим образом:Доступ к переменной класса

#include "X.h" 

class Y 
{ 
    X object; 

public: 
    X & getObject(); 
}; 

Тогда другой файл/класс:

#include "Y.h" 

class Z : public Y 
{ 
    X object2; 
public: 
    X & getObject2(); 
}; 

И, наконец, класс, который получил вектор указателей на объекты.

#include "Z.h" 

class XYZ 
{ 
    vector<Y*> cont; //contains objects of class type Z and Y 
}; 

Если я хочу, чтобы получить доступ к object переменной, я просто пишу

cont[index]->getObject(); 

Но нет никакого способа, чтобы получить доступ к object2, компилятор не увидеть даже такой метод, как getObject2() , Я полагаю, что мое описание не ясное, но в любом случае я надеюсь, что вы мне поможете.

+0

Все остальное в стороне, передача неконстантных ссылок на переменные-члены - это плохая идея, потому что ваш класс просто потерял контроль над своим внутренним состоянием - * имеет * этот элемент управления - это вся идея писать объектно-ориентированное программное обеспечение в первое место. – DevSolar

+3

getObject2 - это функция производного класса, и вы сохраняете указатели на родительский класс. См. Http://www.learncpp.com/cpp-tutorial/121-pointers-and-references-to-the-base-class-of-derived-objects/ для решений. – Chiel

+0

@Chили комментарий в коде ясно указывает, что вектор содержит объекты * обоих * типов. – davmac

ответ

1

Ваша первая проблема заключается в определении того, можете ли вы позвонить по телефону getObject2. Комментарий в вашем коде говорит, что вектор содержит оба типа объектов, поэтому как вы можете быть уверены, что какой-либо конкретный объект является Z, а не только Y? Если это Y, метод getObject2 недоступен, и вы не должны пытаться его вызвать.

У вас есть несколько вариантов. Вот некоторые из них:

  • Одно из решений состоит в использовании двух отдельных векторов для двух различных типов:

    vector<Y*> conty; 
    vector<Z*> contz; 
    

    Однако, это не будет поддерживать порядок между различными типами объектов. Является ли это проблемой или нет, зависит от вашей цели.

  • Другим решением является приведение указателя к нужному типу -

    (Z *)(cont[index])->getObject2(); 
    

    ... но вы можете сделать это, только если вы знаете, фактический тип заостренный-на объект. Вы можете использовать dynamic_cast, если вы не уверены:

    Z *z = dynamic_cast<Z *>(cont[index]); 
    if (z != nullptr) { 
        z.getObject2(); 
    } 
    
  • Еще одним решением является добавление getObject2 в базовый класс, Y, и сделать его виртуальным, так что он может быть переопределен в Z. У вас может быть реализация в Y только для возврата nullptr. Вам нужно будет изменить возвращаемый тип getObject2, чтобы он возвращал указатель, а не ссылку.

    class Y 
    { 
        X object; 
    
    public: 
        X & getObject(); 
        virtual X * getObject2(); 
    }; 
    

Какой вариант лучше всего зависит от ваших конкретных требований.

0

Если то, что вы хотите попробовать это действительно назвать object2(), вы можете попробовать с dynamic_cast набрать Z*. В documentation у вас есть полное объяснение того, как его использовать (например,: Она не сможет возвращать NULL указатель, если вы передаете указатель на объект типа Y)

Z* p_z = dinamic_cast<Z*> (cont[index]) 
if (p_z) 
    std::cout << p_z->getObject2(); 
0

cont является вектором Y*. Это означает, что его члены отображают только API, определенные в классе Y. getObject2() определяется только для его потомков. Даже если элементы в векторе фактически являются экземплярами Z, при условии, что они доступны как экземпляры типа Y, тогда доступен только интерфейс Y.

Если вы хотите getObject2() быть доступны вам нужно сделать один из трех вещей:
1. Добавьте виртуальный getObject2() метод Y
2. Переместить getObject2() функции полностью Y
3. Сделайте contvector<Z*>

1

Кажется, что вам нужны виртуальные функции. Ваш код может быть изменен таким образом:

#include "X.h" 

class Y 
{ 
    X object; 

public: 
    virtual X & getObject() 
    { 
     return object; 
    } 

}; 

и:

#include "Y.h" 

    class Z : public Y 
    { 
     X object2; 
    public: 
     virtual X & getObject() 
     { 
      return object2; 
     } 
    }; 

Так что при любом вызове

cont[index]->getObject(); 

во время выполнения есть смотреть в виртуальной таблице некоторой сущности, указатель которого находится в конце [index]. Если это указатель на объект Y, вызывается getObject() класса Y и если он является указателем на объект Z, вызывается getObject() класса Z.

+0

Я считаю, что это не затрагивает вопрос. OP хочет иметь доступ как к первому, так и к второму объекту в случае, если у них есть объект Z (это не явный, но подразумевается). – davmac

Смежные вопросы