enum {
BT_LEFT = 1,
BT_RIGHT = 2,
BT_ROTATE = 4,
BT_SOFTDROP = 8,
BT_HARDDROP = 16,
BT_PAUSE = 32,
BT_CONNECTED = 32768, // бит, указывающий, что контроллер подключён
};
class Controller { // интерфейс
public:
virtual unsigned poll() const = 0; // сочетание битов BT_XXX
virtual ~Controller = default;
};
// write Intel word
void st::Stream::writeIW(uint16_t w)
{
write(&w, sizeof(uint16_t));
}
Утилита не часть интерфейса, и лучший синтаксис для утилит — методы-расширители C#. На худой конец подойдёт простая функция типа Streams.writeIW(stream, 10);
.// Возвращает остаток потока
// cu_minus = clipped unsigned minus
virtual Pos remainder() { return cu_minus<Pos>(size(),pos()); }
Если в языке нет штатных реализаций, строят класс, где эти функции чем-то реализованы — не всегда, но часто можно унаследоваться от этого класса.std::string commandLine = console.getSomeCommandLine();
Command command;
std::string error;
if (!command.parse(commandLine, error)) {
console.err().writeln(error);
return;
}
Program* program = system.findProgram(command.programName);
if (!program) {
console.err().writeln("Bad command or file name");
return;
}
Console redirectedConsole = console.redirectStreams(command);
program->exec(redirectedConsole, system, command.getArguments());
const std::vector<std::string>& getArguments() const;
const std::vector<std::string>& getOptions() const;
type A = B;
вели к одному «предку». Для этого существует оператор type
.const
FieldSize = 10;
MaxShips = 10;
type
TField = record
cells : array [1..FieldSize, 1..FieldSize] of integer;
nLive : array [1..MaxShips] of integer;
end;
TGame = class
Field : TField;
constructor Create(const Field : TField);
end;
var
x : Test;
....
x.Create(a, b); // неверно!
x := Test.Create(a, b); // верно!
type
DaInt = array of integer;
procedure DoSomething1(var x : array of integer);
procedure DoSomething2(var x : DaInt);
var = null;
Если нужно ещё и мусорщика пустить — ну пусти, System.gc();
doSomething(String data, int start, int length)
, не вытягивая подстроку физически. Использовать StringBuilder. template<>
).///// Защита от повторного включения
#ifndef Unit1H
#define Unit1H
///// Хедеры VCL. Причём всё это сделано так, чтобы упростить написание ценой удлинения
///// компиляции. Более громоздкий, но и более удачный вариант.
///// В H:
///// namespace Controls { class TLabel; }
///// using namespace Controls;
///// В CPP:
///// #include <Controls.hpp>
///// Вот таким образом можно (было) избавиться от каскадного подключения
///// хедера Controls. А то каждый, кто использует главной форму,
///// автоматически подключает эти хедеры.
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
///// Только от Forms.hpp избавиться таким макаром нельзя:
///// мы наследуемся от TForm.
#include <Forms.hpp>
///// Класс формы. Все формы наследуются от TForm.
class TForm1 : public TForm
{
///// Особое право доступа Borland, для совместимости с Delphi.
///// Поля и свойства published не просто public, но включаются
///// в структуру рефлексии (aka reflection или introspection)
///// и программа о них знает при выполнении.
///// Применительно к формам — published-поля доступны
///// загрузчику.
__published: // IDE-managed Components
///// Компоненты, которые мы установили на форме редактором.
TLabel *Label1;
TButton *Button1;
///// События, которые мы прописали в редакторе.
///// __fastcall — модель вызова, аналогичная Delphi.
///// Именно такая модель вызова принята в обработчиках
///// событий.
void __fastcall Button1Click(TObject *Sender);
///// Пользователь пока не прописал никаких своих
///// полей и функций.
private: // User declarations
public: // User declarations
///// Конструктор. Раз уж у формы нетривиальный конструктор —
///// по правилам Си++ его надо повторить в подклассе.
///// Снова-таки, модель вызова __fastcall: в формах Delphi
///// используются т.н. виртуальные конструкторы,
///// когда по имени класса можно создать объект этого класса.
///// Фабричный метод, только немного лучше.
///// Но это значит: у всех подчинённых классов
///// должен быть один и тот же набор параметров
///// и модель вызова.
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
///// Как известно, переменная объявляется один раз.
///// Поскольку хедер может подключаться к огромному числу CPP,
///// её объявляют как extern (она есть, но в другом месте).
///// Макрос PACKAGE раскрывается в __declspec(package),
///// чтобы эту штуку можно было собрать как пакет.
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
class Stream {
public:
virtual void write(size_t length, const void* data) = 0;
// пишет в поток word в машинном порядке байтов
void writeW(uint16_t data) {
write(2, &data);
}
};
class ErpConnector {
public:
// 80% модулей не могут экспортировать данные в систему управления
// предприятием — напишем базовую реализацию.
virtual bool canExportData() const { return false; }
virtual void exportData() const {}
};
void im::DateGrouper::toFirstDateOfPeriod(dt::Date& aDate, int aStart) const
{
aDate = toDate(toInt(aDate, aStart), aStart);
}
void im::MonthGrouper::toFirstDateOfPeriod(dt::Date& aDate, int aStart) const
{
if (aDate.day < aStart)
aDate.addMonthsMechanical(-1); // механически вычесть 1 месяц; дата может стать неверной.
aDate.day = aStart;
aDate.fixupTo1(); // неверную дату привести к 1-му числу следующего месяца
}
someObj.UserData := TObject(true);
someBool := boolean(someObj.UserData);
someObj.UserData := dummyObject;
someBool := (someObj.UserData <> nil);
initialization
dummyObject := TObject.Create;
finalization
dummyObject.Free;
end.
TBoolObject = class
public
Value : boolean;
// конструкторы опущу, деструктор не нужен
end.
someObj.UserData := TBoolObject(true);
someBool := (someObj.UserData as TBoolObject).Value;
TObjBool = record
case integer of
0 : ( asObj : TObject );
1 : ( asBool : boolean );
end;
class Animal {}
class Dog extends Animal {
public void doSound() {}
}
interface Vocal {
void doSound();
}
class Animal {}
class Dog extends Animal implements Vocal {
@Override
public void doSound();
}
if (animal instanceof Vocal)
((Vocal)animal).doSound().
class Animal {
protected:
void doSound();
};
class Dog : public Animal {
public:
using Animal::doSound;
};
protected __property Caption
. И в 99% случаев этого хватает: заглавие отображается где-то — вытягивай наружу. У меня возник вопрос с автоматическим переводом форм. Либо подключай интроспекцию, либо Public Морозов (в Delphi/Builder есть интроспекция и доп. право доступа published, подключающее свойство к ней). Я не стал мучиться и сделал второе.public class Dog extends Animal {
@Override
public void doSound() { super.doSound(); }
}
public static void main(String[] args) {
Animal an = new Animal();
an.doSound(); // protected!
}
class Animal {
public boolean isVocal() { return false; }
public void doSound() {}
}
class Animal {
public Vocal getVocal() { return null; }
}
class Father {};
class Son : private Father {};
int main()
{
Son son;
Father& q = son;
}
#include <iostream>
class Callback {
public:
virtual void act(int x) = 0;
};
void generateFibonacci(int n, Callback& callback) {
int x1 = 0, x2 = 1;
for (int i = 0; i < n; ++i) {
callback.act(x2);
int x3 = x1 + x2;
x1 = x2;
x2 = x3;
}
}
class FileWriter : private Callback {
public:
FileWriter(std::ostream& aOs, int aN) : os(aOs), n(aN) {}
void run() { generateFibonacci(n, *this); }
private:
std::ostream& os;
const int n;
void act(int x) override { os << x << std::endl; }
};
using namespace std;
int main()
{
FileWriter wri(std::cerr, 10);
wri.run();
}
// HEADER
class WebMaster {
public:
WebMaster();
bool connect_open();
private:
static EthernetClient client;
}
// CPP
EthernetClient WebMaster::client;
class WebMaster {
public:
WebMaster();
bool connect_open();
private:
EthernetClient client;
}
// HEADER
class WebMaster {
public:
WebMaster(EthernetClient& aClient);
bool connect_open();
private:
EthernetClient& client;
}
// CPP
WebMaster::WebMaster(EthernetClient& aClient) : client(aClient) {}
...
EthernetClient client;
WebMaster webmaster(client);
data
в реализации item<Edge>
) не имеет конструктора по умолчанию. Есть три пути.class Edge : public EdgeBase
{
public:
Edge (Point* firstPoint, Point* secondPoint) { init(firstPoint, secondPoint); }
Edge () { init(NULL, NULL); }
void init (Point* firstPoint, Point* secondPoint)
{
this->firstPoint = firstPoint;
this->secondPoint = secondPoint;
}
private:
Point* firstPoint;
Point* secondPoint;
};
#include <iostream>
class ImmutableInt
{
public:
explicit ImmutableInt(int x) : fData(x) {}
int data() const { return fData; }
private:
int fData;
};
template <class Payload>
class ListItem
{
public:
Payload payload;
ListItem* next;
ListItem() : next(NULL) {}
ListItem(const Payload& x) : payload(x), next(NULL) {}
};
// Так писать нельзя — эта конструкция расшаблонивает все функции,
// а конструктора по умолчанию как не было, так и нет!
//template class ListItem<ImmutableInt>;
int main()
{
ListItem<ImmutableInt> li(ImmutableInt(42));
std::cout << li.payload.data() << std::endl;
return 0;
}
#include <iostream>
class ImmutableInt
{
public:
explicit ImmutableInt(int x) : fData(x) {}
int data() const { return fData; }
private:
int fData;
};
template <class Payload>
class ListItem
{
public:
Payload payload;
ListItem* next = nullptr;
template<class... Args>ListItem(Args... args) : payload(args...) {}
};
int main()
{
ListItem<ImmutableInt> li(42);
std::cout << li.payload.data() << std::endl;
return 0;
}
explicit
не надо, всё-таки отметил — просто чтобы показать, что во втором случае мы передаём параметром ImmutableInt<42>, а в третьем — 42.template<typename type_t>
struct item
{
item* next;
type_t data;
};