How to provide many constructors, but not too many dependencies?

This is a pretty simple C ++ design question:

I have a class that contains some read-only data after creating an object:

class Foo {
private:
  class Impl;
  Impl* impl_;  
public:
  int get(int i); // access internal data elements
};

Now I would like to implement several ways to build an object Fooand fill it with data: from std::istream, from an iterator, vector, etc. What is the best way to implement this?

I could just add all of these constructors directly to Foo, but I don't want the user Footo include std::istream, etc. I am also worried about classes containing too much code.

What is the most idiomatic way to do this? I suppose add some private function addElementand then define friend factory functions that create objects Foo, read data, call addElementand return the constructed object? Any other options?

+3
source share
6 answers

If you want to build something from a range, perhaps:

class X
{
public:
    template <class InputIterator>
    X(InputIterator first, InputIterator last);
};

Using:

//from array
X a(array, array + array_size);

//from vector
X b(vec.begin(), vec.end());

//from stream
X c((std::istream_iterator<Y>(std::cin)), std::istream_iterator<Y>());
+10
source

Foo, , Foo std:: istream .. , ; Foo, .

std:: istream . , istream, Foo.h, istream Foo.cpp.

, . , . , , . , . .

+1

Foo, , Foo std:: istream ..

istream, , istream.

; Foo, , .

. - .

+1

: .

struct FooBuild
{
  // attributes of Foo
};

class Foo
{
public:
  Foo(const FooBuild&);

private:
  // attributes of Foo, some of them const
};

FooBuild Foo. , , Foo , , , .

python frozenset class:)

+1
0

: 1) ( ) 2) ( ). , .

-, ++, TU. ( , Go, C.) , forward declarations ( ", " ), . ( , , , .) - , ++.

The second can be mitigated either by a general initialization method, which can be called by any ctor, or by a common base. The latter has other advantages, for example, when member initialization can or should be done in the initialization list. Example:

struct SpanBase {
  SpanBase(int start, int stop, int step)
  : start(start), stop(stop), step(step)
  // any complex code in the init list would normally be duplicated
  // in each Span ctor
  {
    IMAGINE("complex code executed by each Span ctor");
    if (start > stop) throw std::logic_error("Span: start exceeds stop");
  }
protected:
  int start, stop, step;
};

struct Span : protected SpanBase {
  // Protected inheritance lets any class derived from Span access members
  // which would be protected in Span if SpanBase didn't exist.  If Span
  // does not have any, then private inheritance can be used.

  Span(int stop) : SpanBase(0, stop, 1) {}
  Span(int start, int stop) : SpanBase(start, stop, 1) {}

  Span(int start, int stop, int step): StepBase(start, stop, step) {}
  // this one could be handled by a default value, but that not always true
};

And finally, C ++ 0x allows you to delegate from one ctor to another, so this whole template is greatly simplified.

0
source

Source: https://habr.com/ru/post/1731707/


All Articles