Упс — Есть ли что-то, что C ++ может сделать лучше, чем D, или что D не может сделать? (пример множественного наследования)

Недавно я заинтересовался изучением языка программирования D. (В частности, D2, к которому на момент написания статьи обращаются люди, поскольку D оригинал сейчас находится в режиме обслуживания для совместимости с существующим кодом.)

Прежде чем я решу, использовать ли C ++ или D (я уже знаю C ++, я ничего не знаю о D), я хочу знать, есть ли что-нибудь, что C ++ делает лучше, чем D? Если вы читаете о D в Интернете, есть много материалов, в которых просто говорится: «Вот пример кода на C ++, вот пример этого кода на D, и посмотрите — он получился намного лучше». Что, конечно, верно для приведенных примеров.

Некоторые различия могут зависеть от мнения. Например, вызов конструктора базового класса из производного класса выполняется super() (D), а не <class name>(args) в списке инициализации (после : обозначения.) (C ++). Лично мне это не нравится super но это только мое мнение, и это не вопрос, который я задаю.

Более уместно, что D не может поддерживать множественное наследование. (!)

  • Что еще не поддерживает D, который поддерживает C ++?
  • Существуют ли примеры того, как C ++ работает лучше в D по какой-то синтаксической или логической причине? (Не основанный на мнениях, но не стесняйтесь отвечать аргументами, основанными на мнении, если они актуальны и конструктивны.)
  • Приводит ли тот факт, что D не поддерживает множественное наследование, к ситуациям, когда вы «заблокированы» от того, что вы можете сделать в C ++? (Я думаю, может быть, iostream / ifstream / ofstream операции?)
  • Есть ли способы обойти запрет на множественное наследование, если оно вам действительно нужно?

Например, одна вещь, которую вы могли бы сделать в C ++, это что-то вроде следующего:

class base
{

}

class base_has_read_operation
{
public:
void read()
{
// complicated read function, 100000 lines of code...
}

virtual void do_read() = 0;

private;
// data
}

class base_has_write_operation
{
public:
void write()
{
// complicated write function, 100000 lines of code
}

virtual void do_write() = 0;

private:
// data
}

class reader : public base_has_read_operation
{
public:
void do_read()
{
read();
}
}

class writer : public base_has_write_operation
{
public:
void do_write()
{
write();
}
}

class read_writer : public base_has_read_operation, base_has_write_operation
{
public:
void do_read()
{
read();
}

void do_write()
{
write();
}
}

Но, вероятно, без множественного наследования вы не можете сделать это?

2

Решение

Ваша проблема множественного наследования может быть решена с помощью шаблона mixin, другими словами, фрагмента кода, который вставляется в другой. Пример:

interface IWriter {
void do_write();
}

// It is a template, you can specify compile-time arguments
mixin template Write() {
// complicated write function
}

interface IReader {
void do_read();
}

mixin template Read() {
// complicated read function
}

// D has multiple interface inheritance
class ReaderWriter : IWriter, IReader {
void do_write {
// You can do other things before...
mixin Write;  // The code of Write is inserted here
// ...or after
}

void do_read {
mixin Read;
}
}

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

4

Другие решения

Я перешел с C ++ на D два месяца назад, так что, возможно, я ошибаюсь.
ref Спецификатор не заменяет ссылки в C ++. В частности, с помощью ссылок и пересылки значений в C ++ 11 вы можете выполнять очень эффективную работу, например, копировать только параметры, если это необходимо. Один из аспектов D, с которым у меня были проблемы, — это тип ссылки и значение. C ++ гораздо более прозрачен для этого.
Это затрудняет написание эффективного кода. Предположим, у вас есть класс C!(T), Вы можете создать T, но если T это класс, вам нужно T t = new T(arg) иначе T t = T(arg), Я использовал миксин и т.п. T t = mixin((is (T == class) ? "new " : "") ~ "T(arg)");, Это довольно некрасиво. В этом случае я бы предпочел объекты значения C ++.

1