Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Вызов конструктора по умолчанию из перегруженого конструктора

590
19 июня 2007 года
Gigahard
223 / / 03.04.2006
имеем некий класс


Код:
class Test
{
    public:
    Test():myValue(0), myData(0), myAnotherValue(0){}
    Test(int* pointer);
    ~Test(){};

    private:
    int myValue;
    int myData;
    int myAnotherValue;
    int* myPointer;
}

В классе определено много переменных, которые инициализируются нулями (или еще какими нибудь значениями).
Есть конструктор по умолчанию, который соответственно делает всю эту работу.

Есть перегруженный конструктор который в добавок проводит инициализацию переменной myPointer. Но при этом еще нужно, чтоб перегруженный конструктор инициализировал остальные переменные, точно так же как конструктор по умолчанию. Самым простым было бы добавить код из конструктора по умолчанию в перегруженный конструктор. Но это плодить лишний код... Можно ли в теле перегруженого конструктора каким либо образом вызвать конструктор по уполчанию, после чего реализовать уже перегруженные операции?
361
19 июня 2007 года
Odissey_
661 / / 19.09.2006
Честно говоря в голову приходит только создание отдельной функции, в которой все это будет инициализироваться, и вызов ее уже и из конструктора по умолчанию, и из остальных конструкторов. Если есть вариант лучше, поделитесь. Самому интересно...
4.3K
19 июня 2007 года
flat
142 / / 27.12.2005
Можно использовать конструктор с параметрами по умолчанию, т.е.
 
Код:
class Test
{
//....
Test(int* pointer = NULL);
//....
}
590
19 июня 2007 года
Gigahard
223 / / 03.04.2006
Т.е. это будет подменять конструктор Test()?
4.3K
19 июня 2007 года
flat
142 / / 27.12.2005
Цитата: Gigahard
Т.е. это будет подменять конструктор Test()?


Т.е. если ты будешь вызывать конструктор без параметров (т.е. конструктор по умолчанию)

 
Код:
Test test_object;

то это будет аналогично вызову
 
Код:
Test test_object(NULL);

В общем нужен всего один конструктор. Выглядит это примерно так:
Код:
class Test
{
//....
  Test(int * pointer = NULL);
//....
};

///////////////////////////////////////////

Test::Test(int * pointer) // здесь pointer инициализировать
                                  // не надо
{
// здесь код, который в твоем
// конструкторе по умолчанию
// [color=gray]смотри не изменяй здесь значение pointer'а[/color]

  if (pointer)
  {
  // здесь код твоего
  // перегруженного конструктора
  }
}
320
19 июня 2007 года
m_Valery
1.0K / / 08.01.2007
Цитата: Odissey_
Честно говоря в голову приходит только создание отдельной функции, в которой все это будет инициализироваться, и вызов ее уже и из конструктора по умолчанию, и из остальных конструкторов. Если есть вариант лучше, поделитесь. Самому интересно...


Посмотри еще Скотта Майерса "Эффективное использование С++".Рекомендует делать именно так,т.е. заменить список инициализации вызовом общей инициализирующей функции.Между инициализацией и присваиванием обьектов встроенного типа(если они не
ссылки и не константные) нет никакого функционального отличия.Совет Майерса относится к случаю,когда имеется большое количество членов класса встроенных типов(как у тебя) и необходимо,чтобы все они инициализировались в каждом конструкторе одинаковым образом.

350
19 июня 2007 года
cheburator
589 / / 01.06.2006
Цитата: Gigahard

Есть перегруженный конструктор который в добавок проводит инициализацию переменной myPointer. Но при этом еще нужно, чтоб перегруженный конструктор инициализировал остальные переменные, точно так же как конструктор по умолчанию. Самым простым было бы добавить код из конструктора по умолчанию в перегруженный конструктор. Но это плодить лишний код... Можно ли в теле перегруженого конструктора каким либо образом вызвать конструктор по уполчанию, после чего реализовать уже перегруженные операции?



Специально для этого придумали такое ООП-понятие, как наследование. Когда имеется существующий код (в данном случае - конструктор, который инициализирует все нулями), но нужно добавить свой код, не заменяя, а используя предыдущий, нужно пользоваться наследованием.
Вот пример:

Код:
// Существующий класс
class Test
{
    public:
    Test():myValue(0), myData(0), myAnotherValue(0){}
    ~Test(){};

    private:
    int myValue;
    int myData;
    int myAnotherValue;
}
// Вот мы добавляем сюда int *myPointer:
class TestWithMyPointer : public Test // вид наследования - public,
    //protected или private - зависит от целей создания класса
    //TestWithMyPointer
{
public:
  TestWithMyPointer (int *pointer)
     :Test(), myPointer(pointer)
  {
  };
private:
  int *myPointer;
};
3
20 июня 2007 года
Green
4.8K / / 20.01.2000
cheburator, автор не расширяет класс новым полем, а лишь вводит новый порядок инициализации существующего поля.
Наследование здесь не при чем.
350
20 июня 2007 года
cheburator
589 / / 01.06.2006
Вот он, Green, а я-то думал, куда он пропал. Сколько можно пить?
Да, судя по представленному коду, член-данные myPointer имеется в базовом классе, и в производном инициализировать его не представляется возможным.
Но все выглядит так, будто автор привел реальную задачу в упрощенном виде, а на самом-то деле член-данные myPointer был внесен в уже существующий класс, в котором изначально его не было (смотрим конструктор Test()).
Если же я ошибаюсь, и myPointer все-таки существует изначально, это означает опять же использование существующего кода с доработками, т. е. имеет смысл воспользоваться наследованием:
Код:
class Test
{
  ...
  Test () ...
}

class Derived : public Test
{
public:
  Derived (int *ptr)
  : Test ()
  {
    myPointer = ptr;
  };
};
3
20 июня 2007 года
Green
4.8K / / 20.01.2000
Ну так использовать наследование можно только а двух случаях:
1) чтоб не трогать чужой класс,
2) ну просто, чтоб было... влепить куда непопадя.

Оба случая к теме не относятся. :)

Что касается темы, то я рекомендую либо создать специальную приватную функцию инициализации и вызывать её из конструктора, либо не ленится создавать два схожих по списку инициализации конструктора, усли списки эти не велики.

Вариант с Test(int* pointer = NULL) мне не нравится, хотя он тоже работоспособный.

P.S. Я не пью. Просто, я в пути на другом континенте, где нет кириллицы на клаве.
590
20 июня 2007 года
Gigahard
223 / / 03.04.2006
Речь идет именно об одном классе с перегруженными конструкторами, а не о наследовании от родительского... Не хочеться плодить сущностей сверх необходимого :)

Разрываюсь между вариантами Odissey_ и flat.
В случае с приватной функцией инициализации, ее можно пихать в любой перегруженый конструктор, а в случае с примером flat, придеться делать один большой суперконструктор, где проверять, инициализированы параметры или нет... Это помниться, я так в PHP конструкторы перегружал :)
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог