void TArray::SetCount (int NewCount)
{[INDENT] if (NewCount == Count) return;
if (NewCount < 0) throw Exception ("");
for (int i = _fCount-1; i >= NewCount; i--)
(_fItems+i)->~TItem(); //Вызов деструктора для элемента массива
_fItems = (TItem*) realloc (_fItems, sizeof(TItem)*NewCount); // Изменение размера выделенной памяти
for (int i = _fCount; i < NewCount; i++)
(_fItems+i)->TItem(); //Вызов конструктора для инициализации элемента массива
_fCount = NewCount
[/INDENT]}
Вызов конструктора
Во время разработки класса, аналогичного DynamicArray (целесообразность этого прошу не обсуждать - просто НАДО), встала проблема изменения кол-ва объектов в массива
Код:
В строке вызова конструктора возникает ошибка компиляции :confused:
Пришлось изменить эту строку так, как написано в DynamicArray.
Код:
new (_fItems+i) TItem();
С этим всё понятно - создание объекта по указанному адресу
А почему всё-таки нельзя прямо вызвать конструктор?
Потому что вызов конструктора напрямую в С++ означает создание временного объекта:
Fraction fr = Fraction(1, 2) + Fraction(3, 5);
Создаются два временных объекта: дроби 1/2 и 3/5, сумма которых помещается в третий временный объект, затем вызывается перегруженный оператор = который должен скопировать содержимое временного объекта в создаваемый объект fr.
А почему всё-таки нельзя прямо вызвать конструктор?[/QUOTE]
Конструктор напрямую вызвать можно.
В твоем случае компилятор ругается потому, что он не может разобрать конструкцию (_fItems+i)->TItem(), т.к. конструктор - метод с именем совпадающим с названием типа.
По мнению компилятора после -> должно идти имя члена, но не тип, а TItem - это в первую очередь тип.
Аналогично не получится вызвать оператор преобразования типа, например operator int().
В таких случаях надо явно указывать, что это метод/оператор, а не название типа:
(_fItems+i)->TItem::TItem();
(_fItems+i)->operator int();
[/QUOTE]
Вызов конструктора не обозначает создание объекта. За создание отвечает оператор new, конструктор же инициализирует объект.
[QUOTE=Svyatozar]
Fraction fr = Fraction(1, 2) + Fraction(3, 5);
Создаются два временных объекта: дроби 1/2 и 3/5, сумма которых помещается в третий временный объект, затем вызывается перегруженный оператор = который должен скопировать содержимое временного объекта в создаваемый объект fr.
[/QUOTE]
Не совсем так. В данном примере будут вызваны:
1) Fraction::Fraction(3, 5)
2) Fraction::Fraction(1, 2)
3) Fraction::operator+
4) Fraction::Fraction( 1/2 + 3/5 )
Ни оператор =, ни конструктор копирования вызваны не будут.
[/QUOTE]
Пардон за неточность терминологии - именно инициализацию объекта по указанному адресу я и имел в виду.
Хотел было сказать "спасибо", но вот только код компилироваться не хочет :(
Код:
AnsiString *pStr = (AnsiString*) malloc (sizeof (AnsiString));
pStr->AnsiString::AnsiString(); // 'AnsiString' is not a member of 'AnsiString'
*pStr = Application->Title;
pStr->~AnsiString(); // Вызов деструктора - ошибок не наблюдается
free (pStr);
pStr->AnsiString::AnsiString(); // 'AnsiString' is not a member of 'AnsiString'
*pStr = Application->Title;
pStr->~AnsiString(); // Вызов деструктора - ошибок не наблюдается
free (pStr);
Код:
#include <malloc.h>
#include <iostream>
using namespace std;
class AnsiString
{
public:
AnsiString() {
cout << "AnsiString()" << endl;
}
~AnsiString() {
cout << "~AnsiString()" << endl;
}
};
int main()
{
AnsiString *pStr = (AnsiString*) malloc (sizeof (AnsiString));
pStr->AnsiString::AnsiString();
pStr->~AnsiString();
free (pStr);
return 0;
}
#include <iostream>
using namespace std;
class AnsiString
{
public:
AnsiString() {
cout << "AnsiString()" << endl;
}
~AnsiString() {
cout << "~AnsiString()" << endl;
}
};
int main()
{
AnsiString *pStr = (AnsiString*) malloc (sizeof (AnsiString));
pStr->AnsiString::AnsiString();
pStr->~AnsiString();
free (pStr);
return 0;
}
у меня компилируется (MSVC 2005).
Кстати, говоря, что конструктор МОЖНО вызвать напрямую, я не делал призыв к действию. Этим лучше не злоупотреблять. :)
Объект можно создать и без оператора new:
Myclass myobject(3, 4);
В данном случае место под объект выделяется без оператора new, и вызывается конструктор.
[QUOTE=Green]Не совсем так. В данном примере будут вызваны:
1) Fraction::Fraction(3, 5)
2) Fraction::Fraction(1, 2)
3) Fraction::operator+
4) Fraction::Fraction( 1/2 + 3/5 )
Ни оператор =, ни конструктор копирования вызваны не будут.[/QUOTE]
согласен что оператор = здесь не будет вызван, хотя он и присутствует. Исправляю свою ошибку. Но с остальным не согласен:
Код:
Fraction fr;
fr = Fraction(1, 2) + Fraction(3, 5);
fr = Fraction(1, 2) + Fraction(3, 5);
Я настаиваю на том что и в исправленном и в неисправленном моем примере создаются временные объекты, например a и b:
Код:
Fraction fr;
{
Fraction b(3, 5);
Fraction a(1, 2);
fr = a.operator+(b);
}
{
Fraction b(3, 5);
Fraction a(1, 2);
fr = a.operator+(b);
}
Что касается прямого вызова конструктора через указатель объекта:
pStr->AnsiString::AnsiString();
gcc такого безобразия не пропустит: "error: invalid use of 'class AnsiString'"
Не совсем так. В данном примере будут вызваны:
1) Fraction::Fraction(3, 5)
2) Fraction::Fraction(1, 2)
3) Fraction::operator+
4) Fraction::Fraction( 1/2 + 3/5 )
Ни оператор =, ни конструктор копирования вызваны не будут.[/QUOTE]
А почему оператор-то = не будет вызываться?
По-моему так будет:
1) Создаеться вр. объект и вызываеться Fraction::Fraction(3, 5)
2) Создаеться вр. объект и вызываеться Fraction::Fraction(1, 2)
3) Создаеться вр. объект и вызываеться Fraction::operator+
4) вызываеться Fraction::operator=
Myclass myobject(3, 4);
В данном случае место под объект выделяется без оператора new, и вызывается конструктор.
[/QUOTE]
Создание объекта - это выделение памяти + вызов конструктора.
Память может быть выделена как в куче (new), так и на стеке.
Я же говорил совсем о другом: вызов конструктора - это ещё не создание объекта в противовес твоим словам "Потому что вызов конструктора напрямую в С++ означает создание временного объекта:"
[QUOTE=Svyatozar]
согласен что оператор = здесь не будет вызван, хотя он и присутствует. Исправляю свою ошибку. Но с остальным не согласен:
Код:
Fraction fr;
fr = Fraction(1, 2) + Fraction(3, 5);
fr = Fraction(1, 2) + Fraction(3, 5);
Я настаиваю на том что и в исправленном и в неисправленном моем примере создаются временные объекты, например a и b:
[/QUOTE]
А кто с этим спорит?
Да, создаются два временных объекта на стеке.
Я перечислил вызовы, которые будут осуществлены, чтобы показать, что оператор = вызван не будет.
[QUOTE=Svyatozar]
Что касается прямого вызова конструктора через указатель объекта:
pStr->AnsiString::AnsiString();
gcc такого безобразия не пропустит: "error: invalid use of 'class AnsiString'"[/QUOTE]
Ну это не безобразие, а вполне нормальная конструкция, например, когда надо вызвать виртуальный метод определенного класса в иерархии.
Возможно, что с конструкторами такое не прокатит, но ответ надо искать в стандарте, а не в реализации какого-либо компилятора.
По-моему так будет:
1) Создаеться вр. объект и вызываеться Fraction::Fraction(3, 5)
2) Создаеться вр. объект и вызываеться Fraction::Fraction(1, 2)
3) Создаеться вр. объект и вызываеться Fraction::operator+
4) вызываеться Fraction::operator=[/QUOTE]
1 и 2 пункты имеют место
3-й пункт выглядит иначе: вызывается operator+ в ходе которого создается объект.
В С++ есть некоторая оптимизация (это не оптимизация оптимизатора), а оптимизация заложенная в сам язык, что в подобных случаях результирующий объект и будет результатом всей строки.
Домашнее задание: найдите это в стандарте, а то вдруг я ошибаюсь :)
Но даже если бы такой оптимизации не было, то оператор = не вызвался, а вызвался бы копирующий конструктор, т.к. в C++ записи
A a = b;
и
A a(b);
тождественны.
1) Создаеться вр. объект и вызываеться Fraction::Fraction(3, 5)
2) Создаеться вр. объект и вызываеться Fraction::Fraction(1, 2)
3) вызываеться Fraction Fraction:operator+(Fraction&, Fraction&)
3.1) return object - вызывается конст. копирования!
В стеке создаеться вр. объект путем копирования object!
4) вызываеться Fraction:operator=(fr, вр. объект из 3.1)
Насчет 4-го сделай ссылку. Руки дойдут почитаю сам стандарт, а пока ...
если очень нужно использовать malloc(), тебе придется перегружать операторы new и delete:
#include <stdlib.h>
class X {
//...
public:
void * operator new(size_t size) {return (malloc(size)); }
void operator delete(void *ptr) { free(ptr); }
X(unsigned size) { new(size); }
~X() { delete(this); }
Как я уже сказал, в моем исправленном примере:
Код:
Fraction fr;
fr = Fraction(1, 2) + Fraction(3, 5);
fr = Fraction(1, 2) + Fraction(3, 5);
operator= вызывается
А что касается стандарта языка, то компилятор от мелкомягких не соответствует стандарту ANSI.
А что касается стандарта языка, то компилятор от мелкомягких не соответствует стандарту ANSI.[/QUOTE]
А какой вообще соответствует? :D
3.1) return object - вызывается конст. копирования!
В стеке создаеться вр. объект путем копирования object!
[/QUOTE]
Не обязательно конструктор копирования, все зависит от реализации оператора +. Скорее всего даже, что не копирования.
[QUOTE='
4) вызываеться Fraction:operator=(fr, вр. объект из 3.1)
Насчет 4-го сделай ссылку. Руки дойдут почитаю сам стандарт, а пока ...[/QUOTE]
Смотри сюда (п.2):
http://www.open-std.org/jtc1/sc22/open/n2356/special.html#class.copy
...
у меня компилируется (MSVC 2005).
Кстати, говоря, что конструктор МОЖНО вызвать напрямую, я не делал призыв к действию. Этим лучше не злоупотреблять. :)[/QUOTE]
Что значит "нет инфы" :confused:.
Общеупотребительный тип C++ Builder'а.
Кстати, то, что Borland C++ Builder 6.0 не компилирует такой код - это баг или стандарт?
Intel C++ compiler 9.1
Общеупотребительный тип C++ Builder'а.
Кстати, то, что Borland C++ Builder 6.0 не компилирует такой код - это баг или стандарт?[/QUOTE]
Просто, у меня нет Builder'а.
А баг это или стандарт - это интересный вопрос, в котором я уже предлагал разобраться.
[QUOTE=Svyatozar]
Intel C++ compiler 9.1
[/QUOTE]
:)
Скажу по секрету: ни один компилятор не соответствует стандарту в полной мере.
Доказательств можно привести множество и в каждом случае они свои.
Но есть и общие черты несоответствия, например, export template.
[/QUOTE]
Хорошая идея, давай разберёмся. Только у меня стандартов под рукой нет :). Кстати, а что конкретно по этому поводу говорит Устав? (пардон, Стандарт :D)
Скажу по секрету: ни один компилятор не соответствует стандарту в полной мере.
Доказательств можно привести множество и в каждом случае они свои.
Но есть и общие черты несоответствия, например, export template.[/QUOTE]
И Слава Богу! Неслыханный маразм этот export template.
Необходимо каждому понять что Шаблоны - это те же макросы: компилятор для каждого типа создает отдельный код следуя этому макросу. Поэтому нельзя скрыть реализацию шаблона в скомпилированной библиотеке. Поэтому никакой export template не нужен, и даже вреден так как вносит ненужную путаницу.
Необходимо каждому понять что Шаблоны - это те же макросы:компилятор для каждого типа создает отдельный код следуя этому макросу.
[/QUOTE]
Ну и что? Не вижу сходства с макросами.
Сравнивать шаблон с макросом все равно, что счёты с компьютером.
[QUOTE=Svyatozar]
Поэтому нельзя скрыть реализацию шаблона в скомпилированной библиотеке. Поэтому никакой export template не нужен, и даже вреден так как вносит ненужную путаницу.[/QUOTE]
И можно (мета-код) и порой нужно. Кстати, Comeau частично поддерживает экспорт шаблонов.
Но изначально я говорил о другом: каждый компилятор в чем-то не соответствует стандарту.
[QUOTE=el scorpio]Хорошая идея, давай разберёмся. Только у меня стандартов под рукой нет :). Кстати, а что конкретно по этому поводу говорит Устав? (пардон, Стандарт :D)[/QUOTE]
Сравнивать шаблон с макросом все равно, что счёты с компьютером.[/QUOTE]а я вижу сходство.[QUOTE=Green]
И можно (мета-код) и порой нужно. Кстати, Comeau частично поддерживает экспорт шаблонов.[/QUOTE]Говорю же: нельзя скрыть реализацию. Вот упертый! И в Comeau тоже нельзя. Он тоже требует исходники в которых описаны шаблонные функции. Нах%р нужен export если я просто include могу сделать????
[QUOTE=Green]Но изначально я говорил о другом: каждый компилятор в чем-то не соответствует стандарту.[/QUOTE]
Согласен, на 100% не соответствуют, но в химии никогда не бывает измеренных абсолютных 100%.
Просто я увидел слово "стандарт" в контексте разговора о Мелкомягких, и тут я просто не мог удержаться. Даже сейчас колотит в судорогах и не отпускает: неврный тик что ли в запущенной стадии?
[/QUOTE]
Так вот при наличии полноценной реализации в компиляторе export, можно скрыть и реализацию шаблонных методов.
[QUOTE=Svyatozar]
Просто я увидел слово "стандарт" в контексте разговора о Мелкомягких, и тут я просто не мог удержаться. Даже сейчас колотит в судорогах и не отпускает: неврный тик что ли в запущенной стадии?
[/QUOTE]
Да относительно нормально всё у MS с поддержкой стандарта. Во всяком случае не хуже, чем у большинства др. компиляторов.
http://anatolix.naumen.ru/files/books/CPPStandard2003.zip[/QUOTE]
Так вот где стандарты зарыты! Эх, жаль раньше не знал: а то бы ответил squirL'у по поводу того, что декларация переменных для блока - это только в С++! "There are four kinds of scopes: function, file, block, and function prototype" - стандарт С ещё 99 года. (Ивините, что не по теме).
[QUOTE=Green]
Так вот где стандарты зарыты! Эх, жаль раньше не знал: а то бы ответил squirL'у по поводу того, что декларация переменных для блока - это только в С++! "There are four kinds of scopes: function, file, block, and function prototype" - стандарт С ещё 99 года. (Ивините, что не по теме).
Не, ты точно не читаешь что я пишу. Так хотя бы прочти что пишет твой долбаный майкрософт: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_core_Templates_vs.._Macros.asp
Шаблоны - как макросы! И компилируются отдельно для каждого типа данных. Нельзя их заранее для всех возможных типов прекомпилировать и поместить в выполняемый файл. Так как же ты их скроешь?? При чем тут реализация?
[QUOTE=Green]Да относительно нормально всё у MS с поддержкой стандарта. Во всяком случае не хуже, чем у большинства др. компиляторов.[/QUOTE]Ты знаком с большинством других компиляторов?
Может не надо офтоп разводить.
Господа модераторы, пожалуйста, вынесите всё вышесказанное про "шаблоны" в отдельную тему.
[/QUOTE]
Да нет, это ты не понимаешь, что я тебе отвечаю.
[QUOTE=Svyatozar]
Так хотя бы прочти что пишет твой долбаный майкрософт: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_core_Templates_vs.._Macros.asp
[/QUOTE]
Ну во-первых, Майкрософт не мой, а жаль... :)
Во-вторых, если ты прочел сам инф. по ссылке, то мог бы увидеть, что там написано следущее: "In many ways, templates work like preprocessor macros.... However, there are many differences between a macro like this:". Я на всякий случай переведу: "Во многих случаях шаблоны работают, как макросы... Однако, есть множество отличий от макросов, как например:"
Я бы рекомендовал почитать Александреску, чтоб понять, что шаблоны далеко не макросы.
[QUOTE=Svyatozar]
Шаблоны - как макросы! И компилируются отдельно для каждого типа данных.
[/QUOTE]
Да, с этим никто не спорит. Шаблоны компилируются в объектный код отдельно для каждого инстанированного типа.
[QUOTE=Svyatozar]
Нельзя их заранее для всех возможных типов прекомпилировать и поместить в выполняемый файл. Так как же ты их скроешь??
[/QUOTE]
Я уже говорил, ты невнимательно читаешь. Шаблоны могут быть предкомпилированы в мета-код, как например, предкомпилируются скрипты языка Python.
[QUOTE=Svyatozar]
При чем тут реализация?
[/QUOTE]
При том, что на должном уровне это пока не реализовано.
[QUOTE=Svyatozar]
Ты знаком с большинством других компиляторов?[/QUOTE]
Я знаком со множеством распространненных компиляторов (MS, gcc в различных вариациях, Metrowerks, Comeau, Borland, Intel, и пр.), так что исходя из правила 20/80, можно сказать, что "знаком с большинством других компиляторов".
P.S. Если хочешь поговорить о проблемах компиляторов и о шаблонах, то давай сделаем это в отдельной теме.
[QUOTE=
3.1) return object - вызывается конст. копирования!
В стеке создаеться вр. объект путем копирования object!
[/QUOTE]
Не обязательно конструктор копирования, все зависит от реализации оператора +. Скорее всего даже, что не копирования.
[/QUOTE]
C 4-м разабрался на вых., а что Вы насчет 3-го говорите?