如何在不将std :: vector作为公共成员的情况下设计C ++类?

时间:2011-12-27 07:48:51

标签: c++ oop vector

我已经看到了这个问题:Class design with vector as a private/public member?,但我觉得它没有回答这个问题。

我有一个名为PrimeSieve的类,可以初始化为PrimeSieve s(10000)来执行操作,例如检查10000以下的数字是否为素数或列出10000以下的所有素数。特别是,我是想知道如何执行后一种功能。

目前,我这样做,我认为这违反了OOP的原则:

class PrimeSieve {
public:
...
     std::vector<long long> primes;

客户端永远不需要更改向量,但是我怎样才能让客户端迭代一些数字下的所有素数的向量(使用像vector.size()这样的东西?我想过一个按值返回向量的访问器方法,但这似乎效率低下。

5 个答案:

答案 0 :(得分:9)

我将该类定义为:

class PrimeSieve 
{
public:

    typedef std::vector<long long>::const_iterator const_iterator;

    const_iterator begin() const  { return primes.begin(); }
    const_iterator end() const  { return primes.end(); }

    long long  operator[](int index) const { return primes[i]; }

    size_t   size() const { return primes.size(); }

    //rest of the members which compute the primes!

private:
   std::vector<long long> primes ;
} ;

我认为该类的用户应该具有对该向量的只读访问权限,因此我在typedef定义中使用了const_iterator。另请注意,operator[]const成员函数,这意味着您只能访问该值,但无法对其进行修改。

用法:

 PrimeSieve sieve(1000); //compute

 //print to stdout
 std::copy(sieve.begin(), 
           sieve.end(), 
           std::ostream_iterator<long long>(std::cout, " "));

答案 1 :(得分:6)

这是一种方法:

class PrimeSieve {
public:
  const std::vector<long long>& getPrimes() const {
    return primes ;
    }
private:
  std::vector<long long> primes ;
} ;

这里没有低效率 - 返回引用至少与返回指针一样有效。并且客户端可以迭代getPrimes返回的向量(自然地使用const_iterator。)

答案 2 :(得分:1)

public:
    const std::vector<long long>* getPrimes() const { return &primes; }
private:
    std::vector<long long> primes;

这使客户端可以访问指向const的{​​{1}}指针,这意味着他们可以迭代它但不能修改它。

(我的语法可能有问题;自从我完成任何严肃的C ++以来已经过了几年)

答案 3 :(得分:1)

基本规则是:
您创建数据成员private&amp;然后提供public / protected成员函数来公开private数据成员上提供的功能/操作。

您应该遵循相同的规则。

答案 4 :(得分:1)

另一种可能性是设计一个特殊的迭代器类:

class PrimeSieve {
  mutable std::vector<long long> primes;
 public:

  class const_iterator;
  friend class const_iterator;
  class const_iterator{   // should probably inherit from some std::iterator class, not sure there
    const PrimeSieve *domain;
    unsigned index;
   public:
    const_iterator(const PrimeSieve &d): domain(&d), index(0) {}
    const long long &operator *() const{return domain->primes[index];}
    const_iterator &operator++(){
      if (++index >= domain->primes.size()) {
        // calculate a number of "new" primes here
      }
      return *this;
    }
  }

  const_iterator begin() const {return const_iterator(*this);}
};

关于这一点的好处是容器现在是“无限的”:根据需要懒惰地计算素数,而不是达到给定的上限。