Наследование, вызов конструктора базового класса
От: blacksun  
Дата: 11.06.11 19:32
Оценка:
Здравствуйте
Вопрос в коде ниже
class A
{
protected:
    int m_x;
public:

    A()
    {
        m_x = 111;
    }
    A(int i)
    {
        m_x = i;
    }
};

class B : public A
{
public:
    int m_x;
public:
    B()
    {
        m_x = 555;
        A(777);                //   <--- Что происходит здесь? Почему не изменяется A::m_x, а изменятся какой-то другой m_x с другим адресом
        //A::m_x = 888;        //  Здесь все ок
    }
};


int _tmain(int argc, _TCHAR* argv[])
{
    B b;

    return 0;
}
Re: Наследование, вызов конструктора базового класса
От: 24  
Дата: 11.06.11 19:39
Оценка:
Здравствуйте, blacksun, Вы писали:

B>B()

B>{
B> m_x = 555;
B> A(777); // <--- Что происходит здесь? Почему не изменяется A::m_x, а изменятся какой-то другой m_x с другим адресом
B> //A::m_x = 888; // Здесь все ок
B>}

Потому что это не вызов конструктора, а создание безымянного объекта типа А. Чтоб вызывался конструктор, нужно проинициализировать базовую часть:

B() : A(777)
{
   ...
}
Re: Наследование, вызов конструктора базового класса
От: const_volatile  
Дата: 11.06.11 19:39
Оценка:
Здравствуйте, blacksun, Вы писали:

B>Вопрос в коде ниже

B>
B>public:
B>    B()
B>    {
B>        m_x = 555;
B>        A(777);                //   <--- Что происходит здесь? Почему не изменяется A::m_x, а изменятся какой-то другой m_x с другим адресом
B>        //A::m_x = 888;        //  Здесь все ок
B>    }
B>


здесь происходит создание временного безымянного объекта класса A и немедленное его уничтожение. правильный синтаксис инициализации выглядит так:

public:
    B() : A(777), m_x (555) {}
Re: Наследование, вызов конструктора базового класса
От: Aleksey_NN  
Дата: 11.06.11 19:39
Оценка:
Потому что ты в конструкторе создаешь новый безымянный объект класса А. В этом экземпляре и меняется значение A::m_x
Конструктор базового класса вызывается так:

B(int i) : A(i)
{
// инициализация B
}
Re: Наследование, вызов конструктора базового класса
От: Ops Россия  
Дата: 11.06.11 19:44
Оценка:
Здравствуйте, blacksun, Вы писали:

B>Здравствуйте

B>Вопрос в коде ниже

Объясните, что Вы хотите сделать.

> Что происходит здесь?


Здесь создается автоматический объект класса A.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[2]: Наследование, вызов конструктора базового класса
От: blacksun  
Дата: 11.06.11 19:54
Оценка:
Здравствуйте, 24, Вы писали:

24>Здравствуйте, blacksun, Вы писали:


B>>B()

B>>{
B>> m_x = 555;
B>> A(777); // <--- Что происходит здесь? Почему не изменяется A::m_x, а изменятся какой-то другой m_x с другим адресом
B>> //A::m_x = 888; // Здесь все ок
B>>}

24>Потому что это не вызов конструктора, а создание безымянного объекта типа А. Чтоб вызывался конструктор, нужно проинициализировать базовую часть:


24>
24>B() : A(777)
24>{
24>   ...
24>}
24>


Вот спасибо, теперь понятно.
А все же, может есть способ явно вызвать конструктор A() и из кода конструктора B() ? Например когда инициализировать A хочется не константой?
Re[2]: Наследование, вызов конструктора базового класса
От: blacksun  
Дата: 11.06.11 19:54
Оценка:
Здравствуйте, Ops, Вы писали:

Ops>Здравствуйте, blacksun, Вы писали:


B>>Здравствуйте

B>>Вопрос в коде ниже

Ops>Объясните, что Вы хотите сделать.


Да просто хочу разобраться в деталях.
Re[3]: Наследование, вызов конструктора базового класса
От: blacksun  
Дата: 11.06.11 19:59
Оценка:
Здравствуйте, blacksun, Вы писали:

B>Здравствуйте, 24, Вы писали:


24>>Здравствуйте, blacksun, Вы писали:


B>>>B()

B>>>{
B>>> m_x = 555;
B>>> A(777); // <--- Что происходит здесь? Почему не изменяется A::m_x, а изменятся какой-то другой m_x с другим адресом
B>>> //A::m_x = 888; // Здесь все ок
B>>>}

24>>Потому что это не вызов конструктора, а создание безымянного объекта типа А. Чтоб вызывался конструктор, нужно проинициализировать базовую часть:


24>>
24>>B() : A(777)
24>>{
24>>   ...
24>>}
24>>


B>Вот спасибо, теперь понятно.

B>А все же, может есть способ явно вызвать конструктор A() и из кода конструктора B() ? Например когда инициализировать A хочется не константой?

Понятно, что можно сделать как-то так:

class A
{
protected:
    int m_x;
public:

    A()
    {
        m_x = 111;
    }
    A(int i)
    {
        m_x = i;
    }

    void init()
    {
        m_x = 999;
    }
};

class B : public A
{
public:
    int m_x;
public:
    B()
    {
        m_x = 555;
        //A::m_x = 888;
        init();
    }
};



Но как насчет вызова конструктора? В чем его отличие от init() ?
Re[4]: Наследование, вызов конструктора базового класса
От: Mr.Delphist  
Дата: 11.06.11 20:27
Оценка:
B>Но как насчет вызова конструктора? В чем его отличие от init() ?

Как минимум в том, что конструктор — это не совсем метод в привычном понимании. Например:
  • только там у тебя есть право присваивать константные поля (без хаков)
  • если в процессе работы конструктора будет брошено исключение, то произойдет автоудаление тех частей создаваемого инстанса, которые уже "прошли госприёмку" (т.е. будут вызваны деструкторы для тех частей, конструкторы которых успели успешно отработать)
  • Re[3]: Наследование, вызов конструктора базового класса
    От: 24  
    Дата: 12.06.11 10:00
    Оценка:
    Здравствуйте, blacksun, Вы писали:

    B>А все же, может есть способ явно вызвать конструктор A() и из кода конструктора B() ?

    Из тела конструктора — нельзя, т.к. конструкторы вызываются по цепочке, и перед началом создания объекта-наследника базовый объект должен быть полностью создан (т.е. базовый конструктор должен быть выполнен до начала выполнения конструктора наследника).

    B>Например когда инициализировать A хочется не константой?

    Передаваемый аргумент может быть и не константным:

    B(int i) : A(i + 2)
    {
       ...
    }
    Re[3]: Наследование, вызов конструктора базового класса
    От: chijo Россия  
    Дата: 01.07.11 07:15
    Оценка: 2 (1)
    Здравствуйте, blacksun, Вы писали:

    B>Здравствуйте, 24, Вы писали:


    24>>Здравствуйте, blacksun, Вы писали:


    B>>>B()

    B>>>{
    B>>> m_x = 555;
    B>>> A(777); // <--- Что происходит здесь? Почему не изменяется A::m_x, а изменятся какой-то другой m_x с другим адресом
    B>>> //A::m_x = 888; // Здесь все ок
    B>>>}

    24>>Потому что это не вызов конструктора, а создание безымянного объекта типа А. Чтоб вызывался конструктор, нужно проинициализировать базовую часть:


    24>>
    24>>B() : A(777)
    24>>{
    24>>   ...
    24>>}
    24>>


    B>Вот спасибо, теперь понятно.

    B>А все же, может есть способ явно вызвать конструктор A() и из кода конструктора B() ? Например когда инициализировать A хочется не константой?

    Способ есть, причем правильнее у потомков всегда явно вызывать конструктор базового класса в списке инициализаций конструктора потомка ( Derived(): B(), {} ). Хотя если вы не определите ни одного конструктора, то будет автоматически сгенерирован компилятором конструктор по умолчанию, который сам вызовет конструктор по умолчанию базового класса(конечно если он есть у него, а если его нет, то будет ошибка компиляции)...
     
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.