#c
#c
Вопрос:
#include<iostream>
using namespace std;
class base
{
protected:
int a;
public:
base(int i)
{
a=i;
}
};
class derived :protected base
{
public:
derived(){}
void show()
{
cout<<a;
}
};
int main()
{
base obj(2);
derived obj1;
obj1.show();
return 0;
}
Почему эта программа выдает ошибку, как в конструкторе derived::derived()
:
ошибка: нет соответствующей функции для вызова
base::base()
Пожалуйста, объясните. Как я прочитал в stackoverflow, в случае наследования как защищенного, защищенные члены базового класса становятся защищенными членами производного класса. Если я ошибаюсь, пожалуйста, поделитесь хорошей ссылкой, чтобы прояснить мое заблуждение
Ответ №1:
После определения конструктора для любого класса компилятор не создает конструктор по умолчанию для этого класса.
Вы определяете параметризованный конструктор( base(int i)
) для base
и, следовательно, компилятор не генерирует конструктор без аргументов для base
.
Разрешение:
Вам нужно будет определить конструктор, не принимающий никаких аргументов для base
себя.
Добавьте это в свой base
класс:
base():a(0)
{
}
Редактировать:
Нужно ли определять конструктор по умолчанию для каждого класса? Или необходимо, чтобы конструктор, соответствующий производному типу, также присутствовал в базовом типе?
Ответ на оба вопроса — НЕТ.
Цель конструкторов в C — инициализировать переменные-члены класса внутри конструктора. Как вы понимаете, компилятор генерирует конструктор по умолчанию (конструктор, который не принимает аргументов) для каждого класса.
Но есть загвоздка, если вы сами определяете (любой) конструктор (с параметрами или без) для своего класса, компилятор больше не генерирует для него конструктор по умолчанию. Рассуждение компилятора здесь таково: «Ха, этот пользователь сам пишет конструктор для своего класса, поэтому, вероятно, ему нужно сделать что-то особенное в конструкторе, чего я не могу сделать или понять», вооруженный этим рассуждением, компилятор просто больше не генерирует конструктор без аргументов по умолчанию.
Ваш приведенный выше код и вы предполагаете наличие конструктора без аргументов по умолчанию (при derived
создании объекта класса). Но поскольку вы уже определили один конструктор для своего base
класса, компилятор применил свои рассуждения и теперь отказывается генерировать какой-либо конструктор аргументов по умолчанию для вашего base
класса. Таким образом, отсутствие конструктора no argument в base
классе приводит к ошибке компилятора.
Комментарии:
1. зачем это нужно? Я создал конструктор без аргументов для производного. пожалуйста, объясните.
2. нужно ли определять конструктор по умолчанию для каждого класса? Или необходимо иметь конструктор, соответствующий производному типу, также присутствующий в базовом типе. Извините, если я ошибаюсь. Пожалуйста, помогите. Или
3. Если вы определяете конструктор, который принимает аргументы, компилятор не будет генерировать конструктор по умолчанию. Вот как работает C . Если вам нужно иметь конструктор, который принимает аргументы и создал производный класс, который не принимает аргументы, какое значение будет
base::a
по умолчанию? Вам нужно определить это с помощью конструктора по умолчанию.4. @gautamkumar: Я обновил ответ, чтобы лучше объяснить его.
Ответ №2:
Вы должны присвоить значение базовому конструктору:
class Derived : protected base
{
public:
Derived() : base(0)
{
}
};
В зависимости от вашей реализации, присвойте значение base
конструктору. Однако вы можете захотеть Derived
, чтобы конструктор также принимал int
в качестве аргумента, а затем передавал его base
единице.
Ответ №3:
Вам необходимо реализовать пустой конструктор в base
base(int)
c-tor или явно вызвать определенный конструктор derived
. Без этого, когда derived
активирован ctor, он пытается вызвать base()
[пустой ctor], и он не существует, и вы получаете свою ошибку.
Ответ №4:
Вы не определили конструктор по умолчанию для Base
..
Когда вы создаете экземпляр экземпляра Derived
, он вызывает Derived()
конструктор, который, в свою очередь, пытается вызвать конструкцию по Base()
умолчанию, которая не существует, поскольку вы ее не определили.
Вы можете либо объявить пустой конструктор для base Base::Base()
, либо вызвать существующий, как показано ниже:
#include<iostream>
using namespace std;
class base
{
protected:
int a;
public:
base(int i)
{
a=i;
}
};
class derived :protected base
{
derived(): Base(123) {} --this will call the Base(int i) constructor)
void show()
{
cout<<a;
}
};
int main()
{
base obj(2);
derived obj1;
obj1.show();
return 0;
}
Комментарии:
1. 1 за упоминание обоих вариантов: либо создайте ctor по умолчанию в base, либо вызовите существующую базу (int) из derived() !