Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: 1 2 [Все]   Вниз
  Печать  
Автор Тема: Странная проблема при вызове конструкторов  (Прочитано 47230 раз)
0 Пользователей и 2 Гостей смотрят эту тему.
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
Как это понимать???
Записан
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 20-04-2008 20:50 » 

Всё логично. Два Default Constructor (1я строка и 3я) - результат собственно конструирования объектов класса der.
Вторая и четвёртая строки - результат локального создания двух безымянных объектов класса base в конструкторе класса der. Если сделаешь классу base ещё и деструктор с выводом сообщения, то легко в этом убедишься.
Отдельный вопрос, почему при передаче строки во втором случае вызывается конструктор класса base без параметров. Если создавать именованный объект, то вызывается конструктор base(char s[]). Если неименованный, то конструктор по умолчанию, если не выполнить явное приведение типа base ((char*)str);.
Записан
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #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
Записан

Странно всё это....
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #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 от Вад » Записан
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #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
Молодой специалист

ru
Offline 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
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 16-05-2008 06:57 » 

lapulya, хм. Я не знаю, по какому принципу я трассировал подобный твоему код в прошлый раз, но почему-то посчитал, что метод вызывается для объекта. Судя по всему, впал в заблуждение - по крайней мере, сейчас мне не удаётся получить тот же результат, всё говорит о том, что происходит конструирование нового объекта. Пока будем считать, что это моя ошибка Улыбаюсь
Записан
lapulya
Молодой специалист

ru
Offline 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
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 16-05-2008 08:17 » 

Вообще говоря, странно, потому что конструктор сам по себе не должен отличаться от других методов класса, кроме автоматической подстановки стартовой инициализации членов этого класса. Но автоматическая инициализация, за неимением явной - это лишь вопрос присутствия скрытого кода, все действия же применяются к уже выделенной в стеке или куче памяти, она же не при вызове метода выделяется. Поэтому не вижу, почему бы конструктору не вызываться повторно, хотя это и выглядит бессмысленным и/или опасным извращением Улыбаюсь)

Тем не менее, если уж вызов this->base::base() возможен, то не понимаю, почему base::base не даёт эффекта. Указание области видимости, вроде, ясно даёт компилятору понять, что речь идёт о методе, а не об объявлении безымянного объекта.
Записан
sss
Специалист

ru
Offline Offline

« Ответ #11 : 16-05-2008 08:56 » 

Оба на сколько эмоций Улыбаюсь ... Конечно, если до конца выверять, то в примерах нет ни одного копирующего конструктора. А в первом топике (вывод в консоль), как могла получиться четвертая строка Default constructor Не понял
Записан

while (8==8)
lapulya
Молодой специалист

ru
Offline 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
Команда клуба

ru
Offline Offline
Пол: Мужской
Я странный


WWW
« Ответ #13 : 16-05-2008 10:36 » 

Код:
base::base()
не чуть не лучше и не хуже
Код:
this->base::base()

меньше прерываний процессора Улыбаюсь
Записан

The CBO without stats is like a morning without coffee. (c) T.Kyte.
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #14 : 16-05-2008 14:28 » 

Не понятно почему ты считаешь, что при указании области видимости конструктор должен отрабатывать как функция
Мне, напротив, непонятно, почему это не так. Ведь если просто base ещё можно по умолчанию интерпретировать как тип, то base::base() как тип интерпретироваться не должно. Или? Понятно, что это философия, и стандарт всех рассудит
Цитата: ANSI ISO/IEC 14882
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. ]
Только не понимаю, чем это мотивировано.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #15 : 17-05-2008 06:19 » 

Код:
this->base::base()

а это компилируется что ли ? Улыбаюсь

и при чём тут прерывания процессора, чёта я не совсем понял
Записан

lapulya
Молодой специалист

ru
Offline Offline

« Ответ #16 : 17-05-2008 10:55 » 

Ну а чего бы ему не компилироваться то? Почему вообще появились в этом сомнения?

Про прерывания процессора я тоже не понял, но воизбежании флуда для себя решил что это шутка (типа для написания последней фразы надо больше писать и типа на обработку этого потребуется больше тактов процессора ))) )
Записан

С уважением Lapulya
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #17 : 17-05-2008 14:45 » 

lapulya, this->base::base()  - ну не знаю , так то компилится, я попробовал , но как-то непривычно и криворуко запись выглядит Улыбаюсь
Записан

lapulya
Молодой специалист

ru
Offline Offline

« Ответ #18 : 17-05-2008 20:31 » 

 Отлично Отлично Отлично ну а вызов просто функции мембера тебя не напрягает? Если он например записан так
this->Base::function() Ага
Записан

С уважением Lapulya
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #19 : 17-05-2008 21:07 » 

lapulya, а я и так не делаю Улыбаюсь Мне проще написать

function();

или

this->function(); //хотя тоже лишнее

а это
this->Base::function()
 - это для статик-мембера
Записан

lapulya
Молодой специалист

ru
Offline Offline

« Ответ #20 : 17-05-2008 21:14 » 

Не, для статик мембера это вообще не скомпилируется (тут же у тебя this написано, а для статика никакого this по определению быть не может), для статика так

Base::function();

да и то если вызов идет из внешнего места для скласса, мембером которого является данный статик метод, а если мы в границах родного класса, тогла и так

function();

прокатит
Записан

С уважением Lapulya
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #21 : 17-05-2008 21:23 » 

lapulya, я не проверял про this->Base::function() для статика. А ты проверял ?

просто в любом случае я так никогда не вызываю
this->....

поэтому и не парюсь никогда такими надуманными проблемами )
Записан

Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #22 : 17-05-2008 21:29 » 

Алексей1153++, Это иногда полезно. Например такой случай
Код:
void SomeClass::setColor(int color)
{
   this->color = color;
}
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #23 : 17-05-2008 21:31 » 

Finch, ду ну, зачем себя запутывать ) Это решается проще

void SomeClass::setColor(int color_in)
{
   m_color = color_in;
}
Записан

Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #24 : 17-05-2008 21:45 » 

Алексей1153++, Я не люблю давать сто имен для одной сушности. Иногда приходится и так писать. Хотя в последнее время внутрении переменные класса я стал обозначать через приставку _ , то есть _color.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #25 : 17-05-2008 21:53 » 

Опааа to Алексей1153++, я был не прав, беру свои слова обратно для статик функции такой вызов
this->Base::function()
корректен, по крайней мере со стороны MS VS 2005 С++ компилятора.

Для статистики ))) все мемберы переменные у меня имеют приставку the типа
class A
{
int theNumber;
};
Записан

С уважением Lapulya
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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 С++, ни на каком другом компиляторе...
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #35 : 01-06-2008 03:51 » 

LifeMaker, тихо сам с собой веду беседу ? Улыбаюсь

вот ведь задел тебя энтот конструктор Отлично
Кем работаешь, ежели не секрет ?
Записан

LifeMaker
Гость
« Ответ #36 : 01-06-2008 07:10 » 

LifeMaker, тихо сам с собой веду беседу ? Улыбаюсь

вот ведь задел тебя энтот конструктор Отлично
я тут человек новый... просто увидел интересный тред и решил оставить коментарии к тем постам, по поводу которых мне есть что сказать. а то ведь участники так и не разгадали Тайну Четвертой Строки...
да и сильно заинтересовало сообщение о this в static-методе... может я чего-то не знаю? было бы игтересно узнать


Кем работаешь, ежели не секрет ?
работаю программистом. пишу на всеми нами любимом, великом детище Б.Страуструпа

Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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 » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #40 : 01-06-2008 08:49 » 

кроме как в объявлении переменной, меня скобки больше нигде не смущаю, наоборот - регулярно использую их в макросах ) Так как там заранее сам не знаешь, что передашь в параметры. Проще скобок понаставить и не париться, пусть там даже (3) получится )
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #43 : 01-06-2008 09:07 » 

LifeMaker, а, точно. Я просто никогда так не делаю, поэтому не обратил внимания. У меня только так:

double* p=0;
DWORD dwdSize=0;
Записан

lapulya
Молодой специалист

ru
Offline 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
Страниц: 1 2 [Все]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines