особенности синтаксиса C++

Landstreicher

Пишу программу, генерирующую код на C++. В некоторых местах нужно вставлять создание объектов, что-то типа ptr = new Obj(args). Пишу что-то в духе (код слегка изменен для наглядности):

print(class_name + "* ptr = new" + class_name + "(");
for (int i = 0; i < argcount; i++) {
if (i > 0) print(",");
print(arg[i]);
}
print(");");

Все работает отлично. Выясняется, что в паре мест объект надо создавать не на куче, а на стеке. Нет проблем:

print(class_name + " obj(");
for (int i = 0; i < argcount; i++) {
if (i > 0) print(",");
print(arg[i]);
}
print(");");

Опс! Оказывается в половине случаев все работает, а в другой половине — очень странные ошибки. Их внимательное разглядывает приводит к выводу, что когда аргументов 0, то "ptr = new Obj;" работает как надо, а вот "Obj obj;" объявляет функцию без аргументов.
Вопрос: почему в языке такой неоднородный синтаксис? Близкие по смыслу операцию ведут себя по разному. Почему синтаксис выделения объекта в стеке должен отличаться от синтаксиса выделения объекта в куче? Если возникают проблемы с Obj то почему тогда работает "new Obj"?

poi1981

потому что new в сях не было. хочешь однообразия - добавляй круглые скобки первому аргументу - Obj;

mira-bella

зря вообще ввели этот синтаксис объявления переменных
лучше использовать вместо этого:

obj_type obj1(construct_args);

вот этот синтаксис:

obj_type obj1 = obj_type(construct_args);

по Страуструпу эти записи эквивалентны по смыслу.

Dasar

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

Ivan8209

> имхо, лучше было сомнительные фичебаги еще кернинговских C-ей
Как ты предлагаешь определять, что возвращает функция?
---
"Narrowness of experience leads to narrowness of imagination."

Landstreicher

> obj_type obj1 = obj_type(construct_args);
А копирований не будет лишних?

Landstreicher

> основная проблема, что разработчики C++ - во всех мелочах, хотели оставить обратную совместимость с C
+1
Кстати, как с этим обстоят дела в C#, Java?

Helga87

Никакой обратной совместимости. Сделаны совершенно новые языки, позаимствовавшие элементы синтаксиса только на уровне идей.

Ivan8209

> +1
Какой предложишь синтаксис указания сигнатуры функции?
---
...Я работаю антинаучным аферистом...

sbs-66

По идее там должен вызываться сначала конструктор, а потом копирующий конструктор. Но оптимизация этого не допустит!

okunek

>А копирований не будет лишних?
Может будет, а может и не будет. Тут стандарт разрешает убрать вызов копирующего конструктора и сразу вызвать конструктор.

erotic

Честно говоря, не видел, где Страуструп об этом пишет, видел даже обратное:
 
complex y = complex(2,0); // создает complex(2,0 затем инициализирует им y

но при практических проверках в MSVS2005 получается, что действительно вызывается обычный конструктор...

SPARTAK3959

И при всех эти извращениях с синтаксисом разработчики С++ забыли добавить возможность для стековых объектов вызова конструкторов в порядке, зависящем от какого-либо условия в программе, без вызова конструкторов копирования, которые в этом случае теоретически не нужны.

poi1981

зачем загромождать язык? синглетоны пишутся в две строчки

SPARTAK3959

А синглтоны-то тут причем? Я хочу вызывать в разном порядке конструкторы самых обычных классов.

poi1981

синглетоны тут при том, что "возможность для стековых объектов вызова конструкторов в порядке, зависящем от какого-либо условия в программе" ими реализуется, в том числе и для "самых обычных классов"

evgen5555

Я хочу вызывать в разном порядке конструкторы самых обычных классов

А зачем это нужно, можно поподробней?

evgen5555

Не синглетон, а фэктори, скорее.

Dasar

> Кстати, как с этим обстоят дела в C#, Java?
C# - пока молодой, соответственно и особых проблем с совместимостью нет.
с Java-ой все проще и сложнее: у java-ы во главу угла ставится переносимость.
соответственно, общая политика разработчиков Java-ы: язык Java-а необходимо как можно меньше менять, и как можно меньше внего вводить новых языковых конструкций. Соответственно - у них нет проблем с поддержкой обратной совместимости, т.к. новые фичи просто не вводятся.
полуисключением стали лишь generic-и, в язык их ввели, но на уровне il-а их нет.

kokoc88

полуисключением стали лишь generic-и
Ага, а полным исключением стали enum'ы, т.к. есть код для jvm 1.4, где некоторые писали переменные с именем enum.

Landstreicher

> Ага, а полным исключением стали enum'ы, т.к. есть код для jvm 1.4, где некоторые писали переменные с именем enum.
Ага, я с таким кодом сталкивался и он у меня не компилился. Был большой геморрой. Вот вам и переносимость Java.

kokoc88

Я думаю, что переносимость тут не при чём. Был изменён язык, потому что это реально требовалось.

gopnik1994

Ага, я с таким кодом сталкивался и он у меня не компилился. Был большой геморрой.
а рефакторинг для кого придумали? Плюс весь проект можно вычистить одним регэкспом...

Landstreicher

> а рефакторинг для кого придумали? Плюс весь проект можно вычистить одним регэкспом...
Это была чужая прога и разбираться в ней никак не хотелось.

enochka1145

Ага, а полным исключением стали enum'ы
Ну, кое-какая защита всё-таки есть. Переменных с именем const или goto не создать, так что когда Java дорастёт до goto, проблем не будет

Dasar

> Я думаю, что переносимость тут не при чём. Был изменён язык, потому что это реально требовалось
Могли все-таки сделать, что enum не был ключевым словом.
можно было даже так сделать:

class enum X
{
A,
B
}

тогда enum был бы контекстно-зависимым ключевым словом.

kokoc88

тогда enum был бы контекстно-зависимым ключевым словом.
Конечно, они много чего могли бы сделать. Но дело в том, что Java - очень простой язык, в отличие от C#, и поэтому для него лучше было сделать enum ключевым словом с простым использованием.
Оставить комментарий
Имя или ник:
Комментарий: