Интернет обошла стороной одна интересная новость: стало известно о том, что, вероятно, в следующий стандарт языка программирования C будут добавлены средства ООП, а именно — классы. При этом судить о том, будет ли это реализовано — ещё рано, так как данный документ не был окончательно принят и не добавлялся в черновой вариант следующего стандарта. Предложение реализовать это поступило ещё в далёком 1995 году неким Robert Jervis, но было принято на WG14 только сейчас.
Попробуем поделить шкуру неубитого медведя и посмотрим, чем это грозит и что это нам даст.
Для этого рассмотрим пару областей данного средства:
GUI
Многим известно, что в этом деле без ООП практически невозможно что-либо сделать по уму. Так, в GTK+ используется имитация ООП посредством GObject.
#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++).
//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