Интересно, почему люди говорят:
Msgstr «Унаследованный класс не наследует конструктор».
Если бы вы могли МОЖЕТ использовать конструктор родительского класса, и конструктор без параметров вызывается автоматически, несмотря ни на что.
Пример:
#include <iostream>
using namespace std;
class A {
private :
int x;
public :
A () {
cout << "I anyway use parameter-less constructors, they are called always" << endl;
}
A (const int& x) {
this->x = x;
cout << "I can use the parent constructor" << endl;
}
};
class B : public A {
private :
int y;
public :
B() {
}
B (const int& x, const int& y) : A (x) {
this->y = y;
}
};
int main() {
B* b = new B(1,2);
B* b1 = new B();
return 0;
}
Так правильно ли говорить, что конструкторы наследуются в c ++? Каково точное определение «унаследовать» в языках программирования?
Заранее спасибо.
Что они имеют в виду, тот конструктор подписи не наследуются.
В вашем примере B
не имеет конструктора, принимающего const int&
хотя его базовый класс делает. В этом смысле он не «унаследовал» конструктор (но все же может использовать его).
Интересно, почему люди говорят: «Унаследованный класс не наследует конструктор».
Возможно, лучше всего это проиллюстрировать на примере:
struct Foo
{
Foo(int, int) {}
};
struct Bar : Foo
{
};
Это означает, что нет Bar::Bar(int, int)
конструктор, который вы можете вызвать, несмотря на существование конструктора с тем же списком параметров в базовом классе. Таким образом, вы не можете сделать это:
Bar b(42, 42);
В C ++ 11 вы можете на самом деле инетить конструкторы, но вы должны быть откровенными об этом:
struct Bar : Foo
{
using Foo::Foo;
};
Теперь вы можете сказать Bar b(42, 42);
Производный класс может / должен видеть конструкторы базового класса, чтобы вызывать их для согласованности. Однако их сигнатура не предоставляется в производном классе, поэтому нельзя создать класс без явно определенного конструктора, который перенаправляет необходимые аргументы в конструктор базового класса.
В C ++ 11 один Можно наследовать конструкторы: Что такое наследование конструктора?
Другой подход к обходу «прокси-конструкторов» в C ++ < 11: Как определить разные типы для одного и того же класса в C ++
Я думаю, что они имеют в виду:
struct A {
A(int, int) { }
};
struct B : public A {
};
int main()
{
A a(1, 2); // ok
B b(1, 2); // error
}
Для сравнения с «не специальными» функциями-членами:
struct A {
void f() { }
};
struct B : public A {
};
int main()
{
A a;
B b;
a.f(); // ok
b.f(); // ok too
}
Но, конечно же, изнутри B
Вы можете позвонить доступным A
конструкторы (как это делают автоматически сгенерированные). То же самое для деструктора.
Обратите внимание, что в C ++ 11 вы можете использовать функцию «наследования конструкторов»:
struct A {
A(int, int) { }
};
struct B : public A {
using A::A;
};
int main()
{
A a(1, 2); // ok
B b(1, 2); // ok now
}
В вашем примере конструктор по умолчанию (как вы говорите, «без параметров») действительно вызывает конструктор A по умолчанию, но это не означает, что B «унаследовал» этот конструктор, только то, что он «имеет к нему доступ». То есть конструктор A по умолчанию доступен изнутри B, но он недоступен извне (никто не может использовать конструктор A по умолчанию извне для создания экземпляра B).
Другой способ взглянуть на это — спросить, что разочаровывает конструкторов и наследование в C ++? Обычный ответ некоторых людей (включая меня) состоит в том, что не существует автоматического средства, позволяющего «проходное» конструирование базовых классов, принимающее аргументы от конструкторов производных классов, без явного объявления и определения последних.