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

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

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