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: Наследование, вызов конструктора базового класса
Здравствуйте, 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: Наследование, вызов конструктора базового класса
Здравствуйте, 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: Наследование, вызов конструктора базового класса
Потому что ты в конструкторе создаешь новый безымянный объект класса А. В этом экземпляре и меняется значение A::m_x
Конструктор базового класса вызывается так:
B(int i) : A(i)
{
// инициализация B
}
Re: Наследование, вызов конструктора базового класса
Здравствуйте, 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, Вы писали:
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]: Наследование, вызов конструктора базового класса
B>Но как насчет вызова конструктора? В чем его отличие от init() ?
Как минимум в том, что конструктор — это не совсем метод в привычном понимании. Например: только там у тебя есть право присваивать константные поля (без хаков)
если в процессе работы конструктора будет брошено исключение, то произойдет автоудаление тех частей создаваемого инстанса, которые уже "прошли госприёмку" (т.е. будут вызваны деструкторы для тех частей, конструкторы которых успели успешно отработать)
Re[3]: Наследование, вызов конструктора базового класса
Здравствуйте, blacksun, Вы писали:
B>А все же, может есть способ явно вызвать конструктор A() и из кода конструктора B() ?
Из тела конструктора — нельзя, т.к. конструкторы вызываются по цепочке, и перед началом создания объекта-наследника базовый объект должен быть полностью создан (т.е. базовый конструктор должен быть выполнен до начала выполнения конструктора наследника).
B>Например когда инициализировать A хочется не константой?
Передаваемый аргумент может быть и не константным:
B(int i) : A(i + 2)
{
...
}
Re[3]: Наследование, вызов конструктора базового класса
Здравствуйте, 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(), {} ). Хотя если вы не определите ни одного конструктора, то будет автоматически сгенерирован компилятором конструктор по умолчанию, который сам вызовет конструктор по умолчанию базового класса(конечно если он есть у него, а если его нет, то будет ошибка компиляции)...