2013-05-03 1 views
0

Я изучаю C++, и у меня есть небольшая проблема. У меня есть класс, который содержит vector<int>. С внешней стороны это vector<int> должно быть доступно, поэтому должно быть возможно добавить/удалить/получить его элементы.Доступ к объекту класса класса C++, но не позволяют его переопределить

Нельзя переопределить объект новым экземпляром. Вот такой пример класса (это minimalized):

class MyClass 
{ 
    public: 
     vector<int>& vec() { return _vec; } 
    private: 
     vector<int> _vec; 
}; 

Э.Г. следующий код работает:

MyClass x; 
x.vec().push_back(0); 
x.vec().push_back(7); 
x.vec().push_back(9); 
cout << c.vec().size() << endl; 

Но, к сожалению, следующий код работает:

MyClass x; 
x.vec() = vector<int>(); 

Я хотел бы запретить это, но я сделал только найти решение, чтобы вернуть указатель типа vector<int> *. Но я понял, что указатели являются «злыми», и я не должен использовать их напрямую, я должен использовать интеллектуальные указатели. Я думаю, что для этой проблемы умный указатель бесполезен, поэтому я не знаю, как решить эту простую проблему: -/

Или просто простой указатель на самое чистое решение?

наилучшими пожеланиями

Кевин

-edit-

В целом я хотел бы сделать что-то, что может быть использовано как follwing C# класс:

public class MyClass 
{ 
    public List<int> List { get; private set; } 

    public MyClass() 
    { 
     List = new List<int>(); 
    } 
} 

Это просто пример и я просто подумал о том, как сделать это на C++. Может быть, в некоторых случаях у меня есть более сложные классы, чем vector<int>/List<int> для включения в другие классы.

Но, возможно, это возможно только путем определения собственных методов (= интерфейса) для внутреннего объекта.

+0

Не возвращайте ссылку и добавьте специальную функцию для добавления значений? Наличие публичной функции, возвращающей ссылку на переменную-член, похоже на то, что переменная-член является общедоступной. –

+0

Указатели не являются злыми, но здесь не помогают. Вы должны скрыть векторную деталь и предоставить правильный интерфейс для управления данными. – hansmaad

+0

, если вы хотите разоблачить все методы вектора, не видите никакого вреда в том, чтобы разоблачить оператор присваивания (в этом случае вы также могли бы наследовать публикацию от вектора, что было бы проще). если вы хотите иметь контроль и разрешать публиковать только некоторые операторы скрыть вектор и написать свои собственные функции прокси – Yuval

ответ

3

Мне кажется неправильным, что единственным приемлемым решением является предоставление функций пересылки для потенциально всех методов в векторном классе.Поэтому я хотел бы предложить альтернативный ответ.

Создайте небольшой класс шаблонов, публично полученный из vector, который скрывает метод operator=, делая его закрытым.

template<class T> 
class immutablevector : public vector<T> 
{ 
    private: 
    immutablevector &operator=(vector<T>); 
}; 

Тогда в MyClass, где вы бы использовали vector, использовать immutablevector вместо этого.

class MyClass 
{ 
    public: 
    immutablevector<int>& vec() { return _vec; } 
    private: 
    immutablevector<int> _vec; 
}; 

Теперь вы можете безопасно получить доступ ко всем векторной функции с помощью метода vec, но вы не сможете назначить новый экземпляр вектора.

+0

Прохладный раствор ;-) Thx –

3

Немного странно, как вы используете идентификатор private. Вы устанавливаете vector<int> как private, а затем создаете общедоступный метод, который дает прямой доступ к этой переменной.

Вы должны вместо этого создать общедоступные методы get() и push_back()

class MyClass{ 
    private: vector<int> _vec; 
    public: 
     vector<int> get(){ return _vec(); } 
     void push_back(int x) { _vec.push_back(x); } 
}; 

//this will work 
MyClass x; 
x.push_back(0); 
x.push_back(7); 
x.push_back(9); 
cout<<x.get().size()<<endl; 

В настоящее время существует не так, как вы напрямую изменить private переменную vector<int> _vec. Имейте в виду, что вам, вероятно, понадобится создать экземпляр _vec в конструкторе MyClass.

+0

Публичный метод для массива векторных частных элементов не так уж плох. Это позволяет, например, добавлять журнал в любое время, когда элемент добавляется в массив, всего в одном месте в коде. – TheDarkKnight

+1

Это правда, но разве это не побеждает цель «частного» спецификатора доступа? – dragos2

+0

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

3

Вы могли бы рассмотреть возможность использования функции только выставить необходимые функции:

class MyClass 
{ 
public: 
    void push_back(int value) { _vec.push_back(value); } 
    size_t size() { return _vec.size(); } 

private: 
    vector<int> _vec; 
}; 

int main() 
{ 
    MyClass x; 
    x.push_back(0); 
    x.push_back(7); 
    x.push_back(9); 
    cout << x.size() << endl; 

    return 0; 
} 

Или же просто использовать обычный вектор.