Про protected-члены класса в C++

В предыдущей записи я рассказывал про проблемы начинающиеся в главе 12 книги Страуструпа. Дальше я столкнулся с другой проблемой, которая, в силу моей неопытности в наследовании классов C++, заставила потрать некоторое время, чтобы разобраться с вопросом.

В 13 главе Бьёрн Страуструп знакомит нас с его интерфейсом, который он предоставляет, для работы с библиотекой FLTK. Смутило меня описание класса Open_polyline, который является производным от класса Shape. Класс Shape является абстрактным классом, предоставляющий интерфейс для работы с точками и формами графических объектов, цветом, стилем отображения и т.д. Ниже код определения данного класса из файла, который лежит на сайте у Страуструпа

class Shape  {	// deals with color and style, and holds sequence of lines
protected:
	Shape() { }
	Shape(std::initializer_list<Point> lst) {
              for (auto i : lst)
                 points.push_back(i); // add() the Points to this Shape
        }                      
	void add(Point p){ points.push_back(p); }
public:
	void draw() const;  // deal with color and draw_lines
private:
	vector<Point> points;	// not used by all shapes
	Color lcolor {fl_color()};
	Line_style ls {0};
	Color fcolor {Color::invisible};
};

Ничего необычного, объявлены конструктор по умолчанию и конструктор, принимающий список инициализации. Данные конструкторы находятся в protected-области, что не позволяет нам создавать объекты данного класса.
Все бы ничего, да вот только как дело доходит до определения производных классов, тут и начинаются вопросы. Рассмотрим уже упомянутый класс Open_polyline (предназначенный для отрисовки фигуры из линий, начальные и конечные точки которой не замыкаются):

struct Open_polyline : Shape { // open sequence of lines
    using Shape::Shape; // use Shape’s constructors (§A.16)
    void add(Point p) { Shape::add(p); }
};

И пример использования:

Open_polyline opl = {
    {100,100}, {150,200}, {250,250}, {300,200}
};

Я попытался повторить увиденное, на что получал ожидаемые ответы от компиляторов:
g++-4.9.2

error: 'Open_polyline::Open_polyline(std::initializer_list<Point>)' is protected

VC++13

IntelliSense: no instance of constructor "Open_polyline::Open_polyline" matches the argument list argument types are: (Point, Point, Point, Point) ProtectedTest

Так как про использование ключевого слова using в рамках наследования ничего прежде сказано не было, я стал искать информацию в стандарте. И через некоторое время наткнулся на §12.9/4, где написано следующее:

A constructor so declared has the same access as the corresponding constructor in X. …

Насколько я понял, никаких изменения в новом стандарте С++14 на эту тему тоже нет. То есть используя конструкцию using Shape::Shape мы скопировали конструкторы базового класса, но они будут находится в protected-секции и использовать их в коде вне производного класса мы не можем. Можно использовать только метод add() для добавления новых точек, так как мы переопределили данный метод в производном классе, но хотелось бы реализовать исходную задумку. Выходом из данной ситуации является определением конструктора вида:

Open_polyline() : Shape() {}
Open_polyline(initializer_list<Point> lst) : Shape{lst} ()

Таким образом мы объявили конструкторы в public-секции, которые мы сможем успешно использовать везде.
Остается только один вопрос: почему Бьёрн Страуструп оставил это в своей редакции?

Реклама