haker-kirik
Гость
|
|
« : 20-04-2008 19:56 » |
|
Вот простой пример: #include <string.h> #include <iostream> using namespace std;
class base { int base_i; public: base(){cout << "Default constructor\n";} base(char s[ ]){cout << "Copy constructor.\n";} };
class der:public base { public: der(char s[ ]) { if (strlen(s)==0) base("N/A"); else base(s); } };
int main() { int (a); der d1(""); der d2("sample str"); cin.get(); return 0; } По идее эта программа должна вывести два раза фразу "Copy constructor.", но на самом деле выводится следующее: Default constructor Copy constructor. Default constructor Default constructor Как это понимать???
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #1 : 20-04-2008 20:50 » |
|
Всё логично. Два Default Constructor (1я строка и 3я) - результат собственно конструирования объектов класса der. Вторая и четвёртая строки - результат локального создания двух безымянных объектов класса base в конструкторе класса der. Если сделаешь классу base ещё и деструктор с выводом сообщения, то легко в этом убедишься. Отдельный вопрос, почему при передаче строки во втором случае вызывается конструктор класса base без параметров. Если создавать именованный объект, то вызывается конструктор base(char s[]). Если неименованный, то конструктор по умолчанию, если не выполнить явное приведение типа base ((char*)str);.
|
|
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #2 : 21-04-2008 04:13 » |
|
согласен с Вадом. строку base(s) заменил на base d1(s); стал вызываться копирующий конструктор. очень странно. должен был и так вызваться. в твоём коде есть ряд ошибок поправил код думаю по коду поймёшь где твои ошибки class base { int base_i; public: base() { std::cout << "Default constructor\n"; } base(const char * s) { std::cout << "Copy constructor.\n"; } };
class der:public base { public: der(const char * s):base(s) { base b1(s); if (strlen(s)==0) base b2("N/A"); else base b3(s); } };
int _tmain(int argc, _TCHAR* argv[]) {
int (a); der d1(""); der d2("sample str"); return 0; }
компилил в VS2003 и в gcc
|
|
|
Записан
|
Странно всё это....
|
|
|
Вад
|
|
« Ответ #3 : 21-04-2008 05:07 » |
|
У меня осталось подозрение, что эти конструкции: if (strlen(s)==0) base ("N/A"); else base (s);
затевались ради вызова конструктора предка для объекта класса der из его же собственного конструктора. Если это так, то правильно будет делать, как у LogRus, der(const char * s):base(s) { ... }
|
|
|
Записан
|
|
|
|
haker-kirik
Гость
|
|
« Ответ #4 : 21-04-2008 14:11 » |
|
Вад, именно так. Я хочу вызвать конструктор класса base, а не создавать отдельный объект. Т.е. я хочу увеличить функциональность класса base за счёт создания производного класса der. В иной реализации данного примера можно и вовсе просто проверять в конструкторе der какое либо условие входящего аргумента и если оно (условие) не выполняется, то обект не создавать, иначе - вызывать конструктор класса base для инициализации нужных значений.
|
|
« Последнее редактирование: 21-04-2008 14:26 от Вад »
|
Записан
|
|
|
|
Вад
|
|
« Ответ #5 : 21-04-2008 14:24 » |
|
В принципе, из конструктора конструктор предка можно вызвать и из тела, причём именно применительно к данному объекту. if (strlen(s)==0) base::base("N/A"); else base::base(s);
Если не указываешь область видимости, компилятор думает, что это конструирование безымянного объекта. А так - вызывает метод для текущего объекта. Но по-мне, так некрасиво рисовать Тогда уж вынести инициализацию в виртуальный метод А отменить конструирование не получится - или делай фабричный метод, или генери исключение из конструктора
|
|
« Последнее редактирование: 21-04-2008 14:29 от Вад »
|
Записан
|
|
|
|
haker-kirik
Гость
|
|
« Ответ #6 : 21-04-2008 21:09 » |
|
Вад, большое спасибо! Теперь-то всё заработало.
|
|
|
Записан
|
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #7 : 16-05-2008 06:03 » |
|
Что заработало? Вообще ничего не понял... Собственно разбираться начал только из-за этого " А так - вызывает метод для текущего объекта." Никогда так не делал, понятно, что так не пишут, но сожрало любопытство, так вот вот исходник #include <iostream>
using namespace std;
class base { int base_i; public: base() { std::cout << "Default constructor\n"; } base(const char * s) { std::cout << "Copy constructor.\n"; } ~base() {std::cout << "destructor.\n";} };
class der:public base { public: der(const char * s):base(s) { if (strlen(s)==0) base::base("N/A"); else base::base(s); } };
int main(int argc, char * argv[]) { // int (a); der d1(""); der d2("sample str"); return 0; }
Результат выполнения Copy constructor. Copy constructor. destructor. Copy constructor. Copy constructor. destructor. destructor. destructor. Так вот при этом base::base("N/A"); и этом base::base(s); происходит создание двух временных объектов Кстати к создателю кода - вопрос, зачем вот это base("N/A"); твоя программа никогда не напишет в консоли "N/A" Итог все что-то поняли и порешали, я вот например ничего не понял... а смысл исходного кода так вообще для меня загадка... если уже внутри конструктора объекта вы решили его не создавать вам может помочь только исключение и более ничего. Итак повторю - я вообще ничего не понял ни одного поста (за исключением второго с которым полностью согласен). Прям моему удивлению нет предела... где должен вызываться конструктор по умолчанию (ну нет в программе места где он вызывается)? Это int (a); просто чума...
|
|
|
Записан
|
С уважением Lapulya
|
|
|
Вад
|
|
« Ответ #8 : 16-05-2008 06:57 » |
|
lapulya, хм. Я не знаю, по какому принципу я трассировал подобный твоему код в прошлый раз, но почему-то посчитал, что метод вызывается для объекта. Судя по всему, впал в заблуждение - по крайней мере, сейчас мне не удаётся получить тот же результат, всё говорит о том, что происходит конструирование нового объекта. Пока будем считать, что это моя ошибка
|
|
|
Записан
|
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #9 : 16-05-2008 08:07 » |
|
Если жуть как надо воспользоваться конструктором как функцией, чисто для спортивного интереса (ну кто ж та делает в жизни...), то надо так переписать конструктор так der(const char * s):base(s) { if (strlen(s)==0) this->base::base("N/A"); else this->base::base(s); }
Еще раз говорю, это никому не надо, но для эксперимента покатит
|
|
|
Записан
|
С уважением Lapulya
|
|
|
Вад
|
|
« Ответ #10 : 16-05-2008 08:17 » |
|
Вообще говоря, странно, потому что конструктор сам по себе не должен отличаться от других методов класса, кроме автоматической подстановки стартовой инициализации членов этого класса. Но автоматическая инициализация, за неимением явной - это лишь вопрос присутствия скрытого кода, все действия же применяются к уже выделенной в стеке или куче памяти, она же не при вызове метода выделяется. Поэтому не вижу, почему бы конструктору не вызываться повторно, хотя это и выглядит бессмысленным и/или опасным извращением ) Тем не менее, если уж вызов this->base::base() возможен, то не понимаю, почему base::base не даёт эффекта. Указание области видимости, вроде, ясно даёт компилятору понять, что речь идёт о методе, а не об объявлении безымянного объекта.
|
|
|
Записан
|
|
|
|
sss
Специалист
Offline
|
|
« Ответ #11 : 16-05-2008 08:56 » |
|
Оба на сколько эмоций ... Конечно, если до конца выверять, то в примерах нет ни одного копирующего конструктора. А в первом топике (вывод в консоль), как могла получиться четвертая строка Default constructor
|
|
|
Записан
|
while (8==8)
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #12 : 16-05-2008 10:13 » |
|
to sss...Конечно, если до конца выверять, то в примерах нет ни одного копирующего конструктора. А в первом топике (вывод в консоль), как могла получиться четвертая строка Default constructor ... Дык, я о чем и говорю! Даже больше, там ни первой, ни третьей строчки быть не может (что уж говорить о четвертой )! to ВадНе понятно почему ты считаешь, что при указании области видимости конструктор должен отрабатывать как функция ведь конструкция base::base() не чуть не лучше и не хуже this->base::base() с точни зрения написания (я про громоздкость), но во втором случае я гарантированно вызываю метод ,хотя подобные рассуждения это чистой воды философия... Все подобные вопросы решает стандарт, там это должно быть описано {если нас слышит Серега, то это я ему }
|
|
« Последнее редактирование: 16-05-2008 10:15 от lapulya »
|
Записан
|
С уважением Lapulya
|
|
|
McZim
|
|
« Ответ #13 : 16-05-2008 10:36 » |
|
base::base() не чуть не лучше и не хуже this->base::base() меньше прерываний процессора
|
|
|
Записан
|
The CBO without stats is like a morning without coffee. (c) T.Kyte.
|
|
|
Вад
|
|
« Ответ #14 : 16-05-2008 14:28 » |
|
Не понятно почему ты считаешь, что при указании области видимости конструктор должен отрабатывать как функция Мне, напротив, непонятно, почему это не так. Ведь если просто base ещё можно по умолчанию интерпретировать как тип, то base::base() как тип интерпретироваться не должно. Или? Понятно, что это философия, и стандарт всех рассудит 12.1 2. A constructor is used to initialize objects of its class type. Because constructors do not have names, they are never found during name lookup; however an explicit type conversion using the functional notation (5.2.3) will cause a constructor to be called to initialize an object. [Note: for initialization of objects of class type see 12.6. ]
Только не понимаю, чем это мотивировано.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #15 : 17-05-2008 06:19 » |
|
this->base::base() а это компилируется что ли ? и при чём тут прерывания процессора, чёта я не совсем понял
|
|
|
Записан
|
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #16 : 17-05-2008 10:55 » |
|
Ну а чего бы ему не компилироваться то? Почему вообще появились в этом сомнения?
Про прерывания процессора я тоже не понял, но воизбежании флуда для себя решил что это шутка (типа для написания последней фразы надо больше писать и типа на обработку этого потребуется больше тактов процессора ))) )
|
|
|
Записан
|
С уважением Lapulya
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #17 : 17-05-2008 14:45 » |
|
lapulya, this->base::base() - ну не знаю , так то компилится, я попробовал , но как-то непривычно и криворуко запись выглядит
|
|
|
Записан
|
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #18 : 17-05-2008 20:31 » |
|
|
|
|
Записан
|
С уважением Lapulya
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #19 : 17-05-2008 21:07 » |
|
lapulya, а я и так не делаю Мне проще написать function(); или this->function(); //хотя тоже лишнее а это this->Base::function() - это для статик-мембера
|
|
|
Записан
|
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #20 : 17-05-2008 21:14 » |
|
Не, для статик мембера это вообще не скомпилируется (тут же у тебя this написано, а для статика никакого this по определению быть не может), для статика так
Base::function();
да и то если вызов идет из внешнего места для скласса, мембером которого является данный статик метод, а если мы в границах родного класса, тогла и так
function();
прокатит
|
|
|
Записан
|
С уважением Lapulya
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #21 : 17-05-2008 21:23 » |
|
lapulya, я не проверял про this->Base::function() для статика. А ты проверял ?
просто в любом случае я так никогда не вызываю this->....
поэтому и не парюсь никогда такими надуманными проблемами )
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #22 : 17-05-2008 21:29 » |
|
Алексей1153++, Это иногда полезно. Например такой случай void SomeClass::setColor(int color) { this->color = color; }
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #23 : 17-05-2008 21:31 » |
|
Finch, ду ну, зачем себя запутывать ) Это решается проще
void SomeClass::setColor(int color_in) { m_color = color_in; }
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #24 : 17-05-2008 21:45 » |
|
Алексей1153++, Я не люблю давать сто имен для одной сушности. Иногда приходится и так писать. Хотя в последнее время внутрении переменные класса я стал обозначать через приставку _ , то есть _color.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #25 : 17-05-2008 21:53 » |
|
Опааа to Алексей1153++, я был не прав, беру свои слова обратно для статик функции такой вызов this->Base::function() корректен, по крайней мере со стороны MS VS 2005 С++ компилятора.
Для статистики ))) все мемберы переменные у меня имеют приставку the типа class A { int theNumber; };
|
|
|
Записан
|
С уважением Lapulya
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #26 : 18-05-2008 08:18 » |
|
Алексей1153++, Я не люблю давать сто имен для одной сушности. Иногда приходится и так писать.
ну, всё зависит от привычки и внимательности Я вот часто бываю невнимателен, поэтому использую префиксы для автокомментирования переменных, что ооочень мне помогает все мемберы переменные у меня имеют приставку the типа class A { int theNumber; };
а я ставлю "m_" )
|
|
|
Записан
|
|
|
|
LifeMaker
Гость
|
|
« Ответ #27 : 31-05-2008 18:49 » |
|
Вот простой пример: ... По идее эта программа должна вывести два раза фразу "Copy constructor.", но на самом деле выводится следующее: Default constructor Copy constructor. Default constructor Default constructor Как это понимать??? На самом деле твою задачу надо было решать так: #include <string.h> #include <iostream> using namespace std;
class base { int base_i; public: base(){cout << "Default constructor\n";} base(char s[ ]){cout << "Copy constructor: " << s << ".\n";} };
class der:public base { public: der(char s[ ]) :base(strlen(s)==0 ? "N/A" : s) { //if (strlen(s)==0) // base("N/A"); //else // base(s); } };
int main() { int (a); der d1(""); der d2("sample str"); cin.get(); return 0; }
Результат такой, как и ожидал автор: Copy constructor: N/A. Copy constructor: sample str.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #28 : 31-05-2008 19:23 » |
|
LifeMaker, он же не правильного вывода хотел добиться, а понять порядок вызовов )
|
|
|
Записан
|
|
|
|
LifeMaker
Гость
|
|
« Ответ #29 : 31-05-2008 19:49 » |
|
Отдельный вопрос, почему при передаче строки во втором случае вызывается конструктор класса base без параметров. Если создавать именованный объект, то вызывается конструктор base(char s[]). Если неименованный, то конструктор по умолчанию, если не выполнить явное приведение типа base ((char*)str);.
меня четвёртая строка тоже сначала в тупик поставила. вроде по всем правилам должен был base(char s[ ]) сработать. но потом всё-таки до меня дошло. C++ позволяет при объявлении переменной взять её название в скобки. Например: int (a); char (*c); float (m[15]);
Вполне валидные, компилящиеся и работающие объявления. Полностью эквивалентные этому: int (a); char (*c); float (m[15]);
В данном случае компилятор воспринял строку "base(s);" как объявление локальной переменной типа base с именем s (да, C++ разрешает давать локальным переменным имена совпадающие с именами формальных параметров). Убедиться, что это действительно так можно изменив код следующим образом: #include <string.h> #include <iostream> using namespace std;
class base { const char* who_am_i; public: base() { cout << "Default constructor\n"; who_am_i = "I am constructed without parameters\n"; } base(char s[ ]) { cout << "Copy constructor.\n"; who_am_i = "I am constructed with char s[] parameter\n"; } void print_about_yourself() { cout << who_am_i; } };
class der:public base { public: der(char s[ ]) { if (strlen(s)==0) base("N/A"); else { base(s); s.print_about_yourself(); } } };
int main() { int (a); der d1(""); der d2("sample str"); cin.get(); return 0; }
Вывод: Default constructor Copy constructor. Default constructor Default constructor I am constructed without parameters
|
|
|
Записан
|
|
|
|
LifeMaker
Гость
|
|
« Ответ #30 : 31-05-2008 20:42 » |
|
Вад, именно так. Я хочу вызвать конструктор класса base, а не создавать отдельный объект. Т.е. я хочу увеличить функциональность класса base за счёт создания производного класса der. В иной реализации данного примера можно и вовсе просто проверять в конструкторе der какое либо условие входящего аргумента и если оно (условие) не выполняется, то обект не создавать, иначе - вызывать конструктор класса base для инициализации нужных значений.
С++ не допускает такого использованияконструкторов, как ты хочешь. Конструктор базового класса всегда вызывается до конструктора унаследованного класса. Поэтому ты не можешь в теле конструктора унаследованного класса решать, то, с каким именно конструктором будет создаваться базовый класс. Ты лишь можешь выбрать один из базовых конструкторов и указать его в строке инициализации с нужными тебе параметрами. Правда ты можешь сконструировать для него параметры сколь угодно сложным способом (например, как в моём примере выше). Если ты этого конструктора не укажешь, будет вызван конструктор по умолчанию (тот, который без параметров). Принять решение о том, чтобы не создавать базовый класс на основе параметров, переданных в унаследованный класс ты не можешь... Как было уже сказано ты можешь бросить исключение в конструкторе унаследованного класса, но это приведёт к тому, что базовый класс будет сначала создан (до исключения), а потом уничтожен (после него). Ну и это не хороший вариант, т.к. нужен будет код обработки исключений. Как уже было сказано, для такой широкой функциональности, которая тебе нужна, нужно использовать фабрики...
|
|
|
Записан
|
|
|
|
LifeMaker
Гость
|
|
« Ответ #31 : 31-05-2008 21:53 » |
|
Прям моему удивлению нет предела... где должен вызываться конструктор по умолчанию (ну нет в программе места где он вызывается)?
ну как где? при создании экземпляра первым всегда вызывается конструктор базового класса (если он не указан явно, компилятор сам вставляет вызов конструктора по умолчанию, т.е. того, у которого нет параметров), затем конструкторы членов (опять же, либо явно, либо дефолтные), затем только собстенный конструктор класса. Это int (a); просто чума... ну а что? вполне валидный код, всё по стандарту. правда конечно смысла тут в этих скобках нет, сам не понимаю, зачем автор кода их туда влепил...
|
|
|
Записан
|
|
|
|
LifeMaker
Гость
|
|
« Ответ #32 : 31-05-2008 23:40 » |
|
Вообще говоря, странно, потому что конструктор сам по себе не должен отличаться от других методов класса, кроме автоматической подстановки стартовой инициализации членов этого класса. Но автоматическая инициализация, за неимением явной - это лишь вопрос присутствия скрытого кода, все действия же применяются к уже выделенной в стеке или куче памяти, она же не при вызове метода выделяется. Поэтому не вижу, почему бы конструктору не вызываться повторно, хотя это и выглядит бессмысленным и/или опасным извращением ) Тем не менее, если уж вызов this->base::base() возможен, то не понимаю, почему base::base не даёт эффекта. Указание области видимости, вроде, ясно даёт компилятору понять, что речь идёт о методе, а не об объявлении безымянного объекта. на самом деле, конструктор всё-таки отличается семантически от всех остальных методов. различие состоит в том, что методы должны вызываться для проинициализированной области памяти (т.е. для сконструированного объекта), а конструктор должен вызываться для неинициализированной области памяти. в конструкцию base::base() действительно заложен смысл сконструировать временный объект(это ведь конструктор, он должен конструировать, а не вызываться пользователем как метод, это его семантика). и эта конструкция доступна не только внутри класса, но и снаружи. вот так... class Point{ public: int x; int y; Point(int X, int Y):x(X),y(Y){} }
int main() { cout << Point::Point(1,2).x << "\n"; /*смысл конструкции - выделить память с стеке и сконструировать в ней временный объект, так изначально и задумывалось */ cout << Point(1,2).x << "\n"; //упрощённая, более привычная, но абсолютно эквивалентная форма return 0; }
в языке оставлена возможность вызывать конструктор, по указателю, вот так: T* t; t->T::T() в частности это можно использовать как вы писали this->base::base() можно и в более извратной форме это использовать, например снаружи а не в классе, по указателю this->, вот так: int main() { int (a); der d1(""); der d2("sample str"); d2.base::base("string"); // такой вот изврат, страшно, ужасно но валидно, и все сработает и не упадёт. cin.get(); return 0; }
такое использование конструкторов это нонсенс. золотое правило - конструктор не должен использоваться для уже сконструированного объекта. this->base::base() - это очень нехорошо. кстати абсолютно неверно говорить, что так никто не пишет. эта возможность вызова конструктора по указателю оставлена в языке не зря. она используется на практике, например в STL, в частности в реализации всем известного std::vector. там необходимо выделить большой фрагмент памяти под несколько объектов и сконструировать их всех. выделение памяти - один раз, а вызовов конструкторов - много. вот здесь программисту и нужна возможность вызвать конструктор вручную, подсунув ему указатель на непроинициализированную память. выглядит это всё примерно вот так: template<class T> class vector{ int _size; T* _base; public: vector(int size); vector(int size,const T& val); ~vector(); ... // и много чего ещё };
template<class T> vector::vector(int size) :_size(size) { _base = (T*)malloc(_size*sizeof(T)); T* elem = _base; for(int i=0; i<_size; i++) { elem->T::T(); elem++; } }
template<class T> vector::vector(int size,const T& val) :_size(size) { _base = (T*)malloc(_size*sizeof(T)); T* elem = _base; for(int i=0; i<_size; i++) { elem->T::T(val); elem++; } }
template<class T> vector::~vector() { T* elem = _base; for(int i=0; i<_size; i++) { elem->T::~T(); elem++; } free(_base); }
такой вот смысл в вызове конструктора (и кстати деструктора тоже) по указателю...
|
|
|
Записан
|
|
|
|
LifeMaker
Гость
|
|
« Ответ #33 : 31-05-2008 23:43 » |
|
Про прерывания процессора я тоже не понял, но воизбежании флуда для себя решил что это шутка (типа для написания последней фразы надо больше писать и типа на обработку этого потребуется больше тактов процессора ))) )
жжошь
|
|
|
Записан
|
|
|
|
LifeMaker
Гость
|
|
« Ответ #34 : 31-05-2008 23:54 » |
|
а это this->Base::function() - это для статик-мембера
Не, для статик мембера это вообще не скомпилируется (тут же у тебя this написано, а для статика никакого this по определению быть не может)
Опааа to Алексей1153++, я был не прав, беру свои слова обратно для статик функции такой вызов this->Base::function() корректен, по крайней мере со стороны MS VS 2005 С++ компилятора.
lapulya, а можешь привести пример static-метода, в котором MS VS 2005 С++ нормально обработает обращение к this? Ибо я абсолютно уверен в твоём первоначальном мнении, что никакого this там и близко быть не может. Ни на MS VS 2005 С++, ни на каком другом компиляторе...
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #35 : 01-06-2008 03:51 » |
|
LifeMaker, тихо сам с собой веду беседу ? вот ведь задел тебя энтот конструктор Кем работаешь, ежели не секрет ?
|
|
|
Записан
|
|
|
|
LifeMaker
Гость
|
|
« Ответ #36 : 01-06-2008 07:10 » |
|
LifeMaker, тихо сам с собой веду беседу ? вот ведь задел тебя энтот конструктор я тут человек новый... просто увидел интересный тред и решил оставить коментарии к тем постам, по поводу которых мне есть что сказать. а то ведь участники так и не разгадали Тайну Четвертой Строки... да и сильно заинтересовало сообщение о this в static-методе... может я чего-то не знаю? было бы игтересно узнать Кем работаешь, ежели не секрет ?
работаю программистом. пишу на всеми нами любимом, великом детище Б.Страуструпа
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #37 : 01-06-2008 07:15 » |
|
LifeMaker, присоединяйся, конечно, всегда рады новым людям ) про корректно определение переменных так int (a); я лично не знал, спасибо за инфу ) Очередной выверт с++ , за что я его и обожаю, собственно а где в статик-методе было this ? Имелось в виду - вызов статика так this->class::method()
|
|
|
Записан
|
|
|
|
LifeMaker
Гость
|
|
« Ответ #38 : 01-06-2008 07:24 » |
|
а, ну если, вызов, то всё верно, никаких проблем. я просто не так понял.
|
|
|
Записан
|
|
|
|
LifeMaker
Гость
|
|
« Ответ #39 : 01-06-2008 08:23 » |
|
про корректно определение переменных так int (a); я лично не знал, спасибо за инфу ) Очередной выверт с++ , за что я его и обожаю, собственно ну этот "выверт" тоже имеет свой смысл. скобки нужны для расстановки приоритетов о объявлении. если, например, посмотреть на арифметические операции: int a; a = 3*(1+2); // необходимое использование скобок. a = (3*22) + 5; // не нужно, но можно a = (21+22); // скобки тоже бесполезны, но привычны и не вызывают изумления a = (1); //уже странновато выглядит, но почему бы и нет. любое арифметическое выражение можно взять в скобки, так... на всякий случай
также и при объявлении переменных. при сложных объявлениях может оказаться, что без скобок никак. например: double *a[10]; // a - массив из десяти double-указателей double (*b)[10]; // b - указатель на массив из десяти double double *(с[10]); // с - массив из десяти double-указателей double (d); // ну и по аналогии, такая конструкция тоже допустима, хотя и не нужна
что бы по правилам языка такую конструкцию отключить, нужно было бы сильно усложнять формальную грамматику языка. а кому оно нужно?
|
|
« Последнее редактирование: 01-06-2008 08:25 от LifeMaker »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #40 : 01-06-2008 08:49 » |
|
кроме как в объявлении переменной, меня скобки больше нигде не смущаю, наоборот - регулярно использую их в макросах ) Так как там заранее сам не знаешь, что передашь в параметры. Проще скобок понаставить и не париться, пусть там даже (3) получится )
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #41 : 01-06-2008 08:53 » |
|
double (*b)[10]; // b - указатель на массив из десяти double
то есть double b[10]; - так более привычно
|
|
|
Записан
|
|
|
|
LifeMaker
Гость
|
|
« Ответ #42 : 01-06-2008 08:57 » |
|
double b[10]; - так более привычно
дык "double b[10];" и "double (*b)[10];" - это не эквивалентные объявления. первое - массив из десяти double, второе - указатель на массив из десяти double
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #43 : 01-06-2008 09:07 » |
|
LifeMaker, а, точно. Я просто никогда так не делаю, поэтому не обратил внимания. У меня только так:
double* p=0; DWORD dwdSize=0;
|
|
|
Записан
|
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #44 : 01-06-2008 21:47 » |
|
LifeMaker, а это this->Base::function() - это для статик-мембера да тут речь шла имеено окорректности вызова (хотя возможно что такое допускают не все компиляторы, стандарт не смотрел) Это Код: int (a); просто чума... То чито так писать можно у меня сомнений не было ))) это еще с С в наследство досталось, я не понял двух вещей: 1. Зачем объяелана переменная 2. Почему она объявлена именно так (устаревшее написание) Мдя... Цитата: lapulya от 16-05-2008 04:03 Прям моему удивлению нет предела... где должен вызываться конструктор по умолчанию (ну нет в программе места где он вызывается)? ну как где? при создании экземпляра первым всегда вызывается конструктор базового класса (если он не указан явно, компилятор сам вставляет вызов конструктора по умолчанию, т.е. того, у которого нет параметров), затем конструкторы членов (опять же, либо явно, либо дефолтные), затем только собстенный конструктор класса. тут я немного проглядел... дело в том, что в том коде, что привел я, вызова констуктора базового класса без параметров не происходит (в результате экспериментов у меня чуть другой код нежели был исходный, поэтому у меня и дыло недоумение) А у товарищей которые писали STL видимо таки были опасения связанные с тем что программист переопределит new... или что-то еще... поскольку при создании массива объектов через new конструктор по умолчанию (а заодно и деструктор при delete []pointer) отработает и так, другое дело конструктор спараметром (как в твоем примере с вектором), тут да... убедил...
|
|
|
Записан
|
С уважением Lapulya
|
|
|
|