Reputation: 3624
I've seen this question: Class design with vector as a private/public member?, but I don't feel that it answers the question.
I have a class called PrimeSieve
that can be initialized as PrimeSieve s(10000)
to perform actions such as checking whether a number under 10000 is prime or listing all the primes under 10000. In particular, I'm wondering how to perform the latter function.
Currently, I'm doing this, which I think violates the principles of OOP:
class PrimeSieve {
public:
...
std::vector<long long> primes;
The client will never need to change the vector, but how can I still allow the client to iterate through a vector of all of the primes under some number (using things like vector.size()
? I've thought about an accessor method that returns the vector by value, but that seems inefficient.
Upvotes: 1
Views: 233
Reputation: 120711
Another possibility is do design a special iterator class:
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);}
};
The good thing about this is that the container is now "infinite": primes are calculated lazily as needed, rather than up to a given upper bound.
Upvotes: 1
Reputation: 361532
I would define the class as:
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 ;
} ;
I think the user of the class should have read-only access to the vector, so I used const_iterator
in the typedef definition. Also note that the operator[]
is a const
member function which means you can only access the value, but cannot modify it.
Usage:
PrimeSieve sieve(1000); //compute
//print to stdout
std::copy(sieve.begin(),
sieve.end(),
std::ostream_iterator<long long>(std::cout, " "));
Upvotes: 9
Reputation: 17114
This is one way to do it:
class PrimeSieve {
public:
const std::vector<long long>& getPrimes() const {
return primes ;
}
private:
std::vector<long long> primes ;
} ;
There is no inefficiency here -- returning a reference is at least as efficient as returning a pointer. And the client can iterate through the vector returned by getPrimes
(using a const_iterator
, naturally).
Upvotes: 6
Reputation: 206546
The basic rule is:
You make the data member private
& then provide public
/protected
member functions to expose the functionality/operations which is provided on the private
data member.
You should follow the same rule here.
Upvotes: 1
Reputation: 54346
public:
const std::vector<long long>* getPrimes() const { return ℙ }
private:
std::vector<long long> primes;
This gives clients access to a const
pointer to primes
which means they can iterate over it but cannot modify it.
(My syntax may be wrong; it's been a few years since I've done any serious C++)
Upvotes: 1