简体   繁体   中英

How to allow access to a vector elements where the vector is a class member?

I'm having a problem encapsulating a vector. This is with pre C++ 11 code.

I have a class, let's call it A, that has a vector of objects as a member variable. I don't want to give direct access to vector to the clients of class A. However as a first stab I exposed the vector.

class A
{
public:

    struct ConnectionEntry
    {
        int portNumber;
        ...
    }

    std::vector<ConnectionEntry> m_connectionList;
private:
}

There are parts of my code where I have to create vectors of class A and iterate through all of them. When I need to access all the elements of m_connectionList I end up with ugly looking code.

vector<A> vecOfA;

for (vector<A>::iterator it = vecOfA.begin; it != vecOfA.end(); it++)
{
    for (vector<A::ConnectionEntry>::iterator conn = it->m_connectionList.begin();
         conn != it->m_connectionList.end();
         conn++)
    {
    }
}

I don't like that I have the vector exposed. I was thinking about implementing the operator[] and size() for class A and forwarding the values from m_connectionList but that doesn't seem clean to me.

Is there a standard way of solving this problem? Encapsulating the vector and only exposing certain parts without having to re-implement all the standard vector functions.

When using C++03, these are the possibilities:

#include <iostream>
#include <vector>

struct Foo {
    struct Bar {
        int value;
    };

    std::vector<Bar> bars;
};

int main() {
    std::vector<Foo> foos;

    for (unsigned int i = 0; i < foos.size(); ++i) {
        for (unsigned int j = 0; j < foos[i].bars.size(); ++j) {
            // do something
        }
    }

    // or

    typedef std::vector<Foo>::iterator FooIt;
    typedef std::vector<Foo::Bar>::iterator BarIt;
    for (FooIt foo = foos.begin(); foo != foos.end(); ++foo) {
        for (BarIt bar = foo->bars.begin(); bar != foo->bars.end(); ++bar) {
            // do something
        }
    }

    return 0;
}

If you ever switch to C++11, you can use range-for loops:

std::vector<Foo> foos;

for (auto const& it : foos) {
    for (auto const& bars : it.bars) {
        // do something
    }
}

Personally, I would do the following:

class A
{
public:


  struct ConnectionEntry
  {
    int portNumber;
    ...
  }

  typedef iterator typename std::vector<ConnectionEntry>::iterator; 
  typedef const_iterator typename std::vector<ConnectionEntry>::const_iterator; 
  // hope I got that one right, I am used to using

  iterator begin() { return m_connectionList.begin(); }
  iterator end() { return m_connectionList.end(); }

  iterator cbegin() const { return m_connectionList.cbegin(); }
  iterator cend() const { return m_connectionList.cend(); }

private:
  std::vector<ConnectionEntry> m_connectionList;
}

And use it like this:

vector<A> vecOfA;

for (vector<A>::iterator it = vecOfA.begin; it != vecOfA.end(); it++)
{
  for (A::iterator conn = it->begin(); conn != it->end(); conn++)
  {
  }
}

Btw will this be ready for ranged for loops when you are able to switch to C++11 in the future.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM