Warum hat `std :: basic_ios` einen öffentlichen Konstruktor?

15

std::basic_ioshat einen öffentlichen Konstruktor :

explicit basic_ios (std::basic_streambuf<CharT,Traits>* sb);

IMO, der einzige Grund für eine Klasse, einen öffentlichen Konstruktor zu haben, ist die Verwendung einer eigenständigen Instanz dieser Klasse in einem Programm. Wenn eine Klasse nur existiert, um andere Klassen davon abzuleiten (wie es der Fall zu sein scheint basic_ios), sollten alle Konstruktoren der Klasse vorhanden sein protected. Die Konstruktoren von std::ios_basesind alle geschützt. Aber aus irgendeinem Grund haben die Designer des Standards diesen einen Konstruktor der basic_iosÖffentlichkeit gemacht.

basic_ioswird als Basisklasse für mehrere Stream-Typen verwendet, und ich kann mir keinen Anwendungsfall vorstellen, in dem Sie einen haben würden, der nicht mindestens ein basic_istreamoder war basic_ostream. Ist dort eines?

Spencer
quelle

Antworten:

1

Der andere Grund für eine Klasse, einen öffentlichen Konstruktor zu haben, besteht darin, dass diese Konstruktorsignatur verfügbar ist, um ein abgeleitetes Objekt zu erstellen:

struct B{
  B(int);
  protected:
  ~B();
  };

 struct A:B{
    private://no effect.
    using B::B;

    public:
    A(void*);
    };

 A a(10);

Der Konstruktor muss in der Basisklasse öffentlich sein, da eine using-Deklaration eines Basiskonstruktors die Zugänglichkeit des geerbten Konstruktors nicht ändert.

Oliv
quelle
2
Scheint vernünftig, außer afaik, der basic_iosctor, der a nimmt, basic_streambuf*ist seit jeher öffentlich using B::B;. Ich gehe davon aus, dass alte Implementierungen nur einen Proxy-Ctor hatten: A(int x) : B(x) {}- was auch dann gut funktioniert, wenn es sich um einen BCtor handelt protected.
Ted Lyngmo
0

Was ich nicht bemerkt hatte , dass std::basic_istream, std::basic_ostreamund std::basic_iostreamhatte auch öffentlichen Bauer (jeweils nimmt eine std::basic_streambuf*).

Dies ermöglicht ein generisches Programmieranalogon des Polymorphismus in der gleichen Weise wie das Pimpl-Idiom.

Auf diese Weise können Sie einen speziellen Streambuf-Typ erstellen und in einem basic_[io] verwenden, streamohne spezielle Stream-Klassen erstellen zu müssen. (Die Funktionalität ist eingeschränkt: Sie können nicht demselben Stream einen neuen Puffer zuweisen, und Sie müssen die Lebensdauer und den Besitz des Puffers extern verfolgen.)

Die spezialisierten basic_[io] fstreamund basic_[io] stringstreamenthalten jeweils eine vollständige Instanz des zugeordneten Puffertyps. Dies bedeutet, dass eine Instanz eines spezialisierten Stream-Typs nur mit seinem internen Puffer funktioniert und nicht mit einem anderen, nicht einmal mit einem vom gleichen Typ. Die Verwendung eines rohen basic_[io] streamist eine (klobige) Problemumgehung.

template<class C, class TR>
class snazzy_filebuf: public std::basic_streambuf<C, TR>
{
 protected:
   typename TR::int_type overflow(TR::int_type) override;
   typename TR::int_type underflow(TR::int_type) override;
   typename TR::int_type pbackfail(TR::int_type) override;
 public:
   snazzy_filebuf();
};

.....
snazzy_filebuf<char> buf;
std::basic_ostream<char> o_s(&buf); 

o_s << "Hello, world\n";
Spencer
quelle