Будущее C: ООП

в 7:43, , рубрики: C, c++, будущее рядом, ооп, Программирование, разрыв шаблона, метки:

Интернет обошла стороной одна интересная новость: стало известно о том, что, вероятно, в следующий стандарт языка программирования C будут добавлены средства ООП, а именно — классы. При этом судить о том, будет ли это реализовано — ещё рано, так как данный документ не был окончательно принят и не добавлялся в черновой вариант следующего стандарта. Предложение реализовать это поступило ещё в далёком 1995 году неким Robert Jervis, но было принято на WG14 только сейчас.

Попробуем поделить шкуру неубитого медведя и посмотрим, чем это грозит и что это нам даст.

Для этого рассмотрим пару областей данного средства:

GUI

Многим известно, что в этом деле без ООП практически невозможно что-либо сделать по уму. Так, в GTK+ используется имитация ООП посредством GObject.

Hello, world!

#include <gtk/gtk.h>
 
int main (int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *label;
 
    gtk_init(&argc, &argv);
 
    /* Create the main, top level window */
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
    /* Give it the title */
    gtk_window_set_title(GTK_WINDOW(window), "Hello, world!");
 
    /* Center the window */
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
 
    /* Set the window's default size */
    gtk_window_set_default_size(GTK_WINDOW(window), 200, 100);
 
    /*
    ** Map the destroy signal of the window to gtk_main_quit;
    ** When the window is about to be destroyed, we get a notification and
    ** stop the main GTK+ loop by returning 0
    */
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
 
    /*
    ** Assign the variable "label" to a new GTK label,
    ** with the text "Hello, world!"
    */
    label = gtk_label_new("Hello, world!");
 
    /* Plot the label onto the main window */
    gtk_container_add(GTK_CONTAINER(window), label);
 
    /* Make sure that everything, window and label, are visible */
    gtk_widget_show_all(window);
 
    /*
    ** Start the main loop, and do nothing (block) until
    ** the application is closed
    */
    gtk_main();
 
    return 0;
}

Мы наблюдаем классическую для C картину — управление данными в стеке через указатели. Это требует дополнительного внимания к объявлению этих самых указателей. Также это заметно отразится на сопровождению кода.

Вместо этого можно было бы использовать “нативный” подход к разработке, как это реализовано в GTKMM (C++).

Hello, world!

//HelloWorldWindow.h
#ifndef HELLOWORLDWINDOW_H
#define HELLOWORLDWINDOW_H
 
#include <gtkmm/window.h>
#include <gtkmm/button.h>
 
// Derive a new window widget from an existing one.
// This window will only contain a button labelled "Hello World"
class HelloWorldWindow : public Gtk::Window
{
  public:
    HelloWorldWindow();
 
  protected:
    void on_button_clicked(); //event handler
 
    Gtk::Button hello_world;
};
 
#endif

//HelloWorldWindow.cc
#include <iostream>
#include "HelloWorldWindow.h"
 
HelloWorldWindow::HelloWorldWindow()
 : hello_world("Hello World")
{
    // Set the title of the window.
    set_title("Hello World");
 
    // Add the member button to the window,
    add(hello_world);
 
    // Handle the 'click' event.
    hello_world.signal_clicked().connect(
        sigc::mem_fun(*this, &HelloWorldWindow::on_button_clicked));
 
    // Display all the child widgets of the window.
    show_all_children();
}
 
void HelloWorldWindow::on_button_clicked()
{
    std::cout << "Hello world" << std::endl;
}

//main.cc
 
#include <gtkmm/main.h>
#include "HelloWorldWindow.h"
 
int main(int argc, char *argv[]) 
{
    // Initialization
    Gtk::Main kit(argc, argv);
 
    // Create a hello world window object
    HelloWorldWindow example;
 
    // gtkmm main loop
    Gtk::Main::run(example);
    return 0;
}

Это, бесспорно, выглядит более многословно, но пропадаются проблемы, присущие указателям, такие как утечки памяти, ошибки разыменования, удаление NULL-указателей. Также мы сразу же получаем преимущества ООП, такие как инкапсуляция, полиморфизм и наследование. Это явно находит применение в данной области, особенно наследование.

Низкоуровневое программирование

Одна из основных ниш, которую занимает этот пресловутый язык. Решить подобную проблему на C можно разными способами, но наиболее часто встречается непосредственное обращение к регистрам машины.

PORTD = 0xff;

Но это содержит очевидные минусы: лёгкость совершить опечатку, генерирует повторяющийся код, неудобочитаемость и сложность сопровождения.

Более удобно было бы реализовать простенький класс.

class led {
public:
	led: port {*s}{/*..*/}
	ledOn(nuber) {/*...*/};
//...	
};

И в дальнейшем создавать объект для каждого порта. Также можно добавить в конструктор дополнительные параметры, определяющие настройку портов, не говоря уже о огромном множестве всевозможных методов для сложных манипуляций, к примеру, всех разрядов порта.

Проблемный вопрос

В любом случае, области применения данного средства очевидны. Они расширяют функционал языка, делая его не только эффективным, но и более удобным. Из объективной точки зрения это вполне нужно, но… Думаю, у многих ещё при чтении заголовка возник внутренний диссонанс, ведь для этого есть C++. Но разве это ограничит сам C? Кому это должно навредить? Язык уже не так и молод, успел создать массу устойчивых стереотипов, но время идёт, пришло время меняться, и принимать необходимость как должное.

Автор: wwwriter

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js