Как вызвать конструктор c
Перейти к содержимому

Как вызвать конструктор c

  • автор:

Использование конструкторов (Руководство по программированию на C#)

При создании экземпляра класса или структуры вызывается его конструктор. Конструкторы имеют имя, совпадающее с именем класса или структуры, и обычно инициализируют члены данных нового объекта.

В следующем примере класс с именем Taxi определяется с помощью простого конструктора. Затем оператор new создает экземпляр этого класса. Конструктор Taxi вызывается оператором new сразу после того, как новому объекту будет выделена память.

public class Taxi < public bool IsInitialized; public Taxi() < IsInitialized = true; >> class TestTaxi < static void Main() < Taxi t = new Taxi(); Console.WriteLine(t.IsInitialized); >> 

Конструктор, который не принимает никаких параметров, называется конструктором без параметров. Конструкторы без параметров вызываются всякий раз, когда создается экземпляр объекта с помощью оператора new , а аргументы в new не передаются. В C# 12 представлены основные конструкторы. Основной конструктор задает параметры, которые необходимо предоставить для инициализации нового объекта. Дополнительные сведения см. в разделе Конструкторы экземпляров.

Если класс не является статическим, компилятор C# выделяет классам без конструкторов открытый конструктор без параметров, позволяющий создавать экземпляры классов. Дополнительные сведения см. в статье Статические классы и члены статических классов.

Создание экземпляров класса можно запретить, сделав конструктор закрытым, следующим образом:

class NLog < // Private Constructor: private NLog() < >public static double e = Math.E; //2.71828. > 

Дополнительные сведения см. в разделе Закрытые конструкторы.

Конструкторы для типов структур похожи на конструкторы классов. При создании экземпляра new типа структуры вызывается конструктор. struct Если задано значение, default среда выполнения инициализирует всю память в структуре до 0. До C# 10 не может содержать явный конструктор без параметров, structs так как он предоставляется компилятором автоматически. Дополнительные сведения см. в разделе инициализации структуры и значенийпо умолчанию статьи «Типы структур».

В следующем коде используется конструктор Int32без параметров, чтобы убедиться, что целое число инициализировано:

int i = new int(); Console.WriteLine(i); 

Однако следующий код вызывает ошибку компилятора, так как она не используется new , и потому что пытается использовать объект, который не был инициализирован:

int i; Console.WriteLine(i); 

Кроме того, объекты на основе structs (включая все встроенные числовые типы) можно инициализировать или назначить, а затем использовать, как в следующем примере:

int a = 44; // Initialize the value type. int b; b = 33; // Or assign it before using it. Console.WriteLine(", ", a, b); 

Классы и структуры могут определять конструкторы, которые принимают параметры, включая первичные конструкторы. Конструкторы, принимающие параметры, необходимо вызывать с помощью оператора new или base. Классы и структуры также могут определять несколько конструкторов, и для определения конструктора без параметров не требуется. Например:

public class Employee < public int Salary; public Employee() < >public Employee(int annualSalary) < Salary = annualSalary; >public Employee(int weeklySalary, int numberOfWeeks) < Salary = weeklySalary * numberOfWeeks; >> 

Этот класс можно создать, воспользовавшись одним из следующих операторов:

Employee e1 = new Employee(30000); Employee e2 = new Employee(500, 52); 

Конструктор может использовать ключевое слово base для вызова конструктора базового класса. Например:

public class Manager : Employee < public Manager(int annualSalary) : base(annualSalary) < //Add further instructions here. >> 

В этом примере конструктор базового класса вызывается перед выполнением соответствующего ему блока. Ключевое слово base можно использовать как с параметрами, так и без них. Любые параметры для конструктора можно использовать как параметры для base или как часть выражения. Для получения дополнительной информации см. базу.

В производном классе, если конструктор базового класса не вызывается явным образом с помощью base ключевое слово, конструктор без параметров, если есть один, вызывается неявно. Следующие объявления конструктора фактически одинаковы:

public Manager(int initialData) < //Add further instructions here. >
public Manager(int initialData) : base() < //Add further instructions here. >

Если базовый класс не предлагает конструктор без параметров, производный класс должен выполнить явный вызов базового конструктора с помощью base .

Конструктор может вызывать другой конструктор в том же объекте с помощью ключевого слова this. Как и base , this можно использовать с параметрами или без, а все параметры в конструкторе доступны как параметры this или как часть выражения. Например, второй конструктор в предыдущем примере можно переписать, используя this :

public Employee(int weeklySalary, int numberOfWeeks) : this(weeklySalary * numberOfWeeks)

Применение ключевого слова this в приведенном выше примере привело к вызову конструктора:

public Employee(int annualSalary)

Конструкторы могут иметь пометку public, private, protected, internal, protected internal или private protected. Эти модификаторы доступа определяют, каким образом пользователи класса смогут создавать класс. Дополнительные сведения см. в статье Модификаторы доступа.

Конструктор можно объявить статическим, используя ключевое слово static. Статические конструкторы вызываются автоматически, непосредственно перед доступом к любым статическим полям и используются для инициализации элементов статического класса. Дополнительные сведения см. в разделе Статические конструкторы.

Спецификация языка C#

Дополнительные сведения см. в разделах Конструкторы экземпляров и Статические конструкторы в Спецификации языка C#. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.

См. также

  • Система типов C#
  • Конструкторы
  • Методы завершения

Совместная работа с нами на GitHub

Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.

Как вызвать конструктор c

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

В прошлой теме был разработан следующий класс:

#include class Person < public: std::string name; unsigned age; void print() < std::cout >; int main() < Person person; // вызов конструктора person.name = "Tom"; person.age = 22; person.print(); >

Здесь при создании объекта класса Person, который называется person

Person person;

вызывается конструктор по умолчанию . Если мы не определяем в классе явным образом конструктор, как в случае выше, то компилятор автоматически компилирует конструктор по умолчанию. Подобный конструктор не принимает никаких параметров и по сути ничего не делает.

Теперь определим свой конструктор. Например, в примере выше мы устанавливаем значения для полей класса Person. Но, допустим, мы хотим, чтобы при создании объекта эти поля уже имели некоторые значения по умолчанию. Для этой цели определим конструктор:

#include class Person < public: std::string name; unsigned age; void print() < std::cout Person(std::string p_name, unsigned p_age) < name = p_name; age = p_age; std::cout >; int main() < Person tom("Tom", 38); // создаем объект - вызываем конструктор tom.print(); >

Теперь в классе Person определен конструктор:

Person(std::string p_name, unsigned p_age)

По сути конструктор представляет функцию, которая может принимать параметры и которая должна называться по имени класса. В данном случае конструктор принимает два параметра и передает их значения полям name и age, а затем выводит сообщение о создании объекта.

Если мы определяем свой конструктор, то компилятор больше не создает конструктор по умолчанию. И при создании объекта нам надо обязательно вызвать определенный нами конструктор.

Вызов конструктора получает значения для параметров и возвращает объект класса:

Person tom("Tom", 38);

После этого вызова у объекта person для поля name будет определено значение «Tom», а для поля age — значение 38. Вполедствии мы также сможем обращаться к этим полям и переустанавливать их значения.

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

Person tom;

Тажке можно присвоить объекту результат вызова конструктора:

Person tom = Person("Tom", 38);

По сути она будет эквивалетна предыдущей.

Консольный вывод определенной выше программы:

Person has been created Name: Tom Age: 38

Конструкторы облегчают нам создание нескольких объектов, которые должны иметь разные значения:

#include class Person < public: std::string name; unsigned age; void print() < std::cout Person(std::string p_name, unsigned p_age) < name = p_name; age = p_age; std::cout >; int main() < Person tom; Person bob; Person sam; tom.print(); bob.print(); sam.print(); >

Здесь создаем три разных объекта класса Person (условно трех разных людей), и соответственно в данном случае консольный вывод будет следующим:

Person has been created Person has been created Person has been created Name: Tom Age: 38 Name: Bob Age: 42 Name: Sam Age: 25

Определение нескольких конструкторов

Подобным образом мы можем определить несколько конструкторов и затем их использовать:

#include class Person < std::string name<>; unsigned age<>; public: void print() < std::cout Person(std::string p_name, unsigned p_age) < name = p_name; age = p_age; >Person(std::string p_name) < name = p_name; age = 18; >Person() < name = "Undefined"; age = 18; >>; int main() < Person tom; // вызываем конструктор Person(std::string p_name, unsigned p_age) Person bob; // вызываем конструктор Person(std::string p_name) Person sam; // вызываем конструктор Person() tom.print(); bob.print(); sam.print(); >

В классе Person определено три конструктора, и в функции все эти конструкторы используются для создания объектов:

Name: Tom Age: 38 Name: Bob Age: 18 Name: Undefined Age: 18

Хотя пример выше прекрасно работает, однако мы можем заметить, что все три конструктора выполняют фактически одни и те же действия — устанавливают значения переменных name и age. И в C++ можем сократить их определения, вызова из одного конструктора другой и тем самым уменьшить объем кода:

#include class Person < std::string name<>; unsigned age<>; public: void print() < std::cout Person(std::string p_name, unsigned p_age) < name = p_name; age = p_age; std::cout Person(std::string p_name): Person(p_name, 18) // вызов первого конструктора < std::cout Person(): Person(std::string("Undefined")) // вызов второго конструктора < std::cout >; int main() < Person sam; // вызываем конструктор Person() sam.print(); >

Запись Person(string p_name): Person(p_name, 18) представляет вызов конструктора, которому передается значение параметра p_name и число 18. То есть второй конструктор делегирует действия по инициализации переменных первому конструктору. При этом второй конструктор может дополнительно определять какие-то свои действия.

Таким образом, следующее создание объекта

Person sam;

будет использовать третий конструктор, который в свою очередь вызывает второй конструктор, а тот обращается к первому конструктору.

Данная техника еще называется делегированием конструктора , поскольку мы делегируем инициализацию другому конструктору.

Параметры по умолчанию

Как и другие функции, конструкторы могут иметь параметры по умолчанию:

#include class Person < std::string name; unsigned age; public: // передаем значения по умолчанию Person(std::string p_name = "Undefined", unsigned p_age = 18) < name = p_name; age = p_age; >void print() < std::cout >; int main() < Person tom; Person bob; Person sam; tom.print(); // Name: Tom Age: 38 bob.print(); // Name: Bob Age: 18 sam.print(); // Name: Undefined Age: 18 >

Инициализация констант и списки инициализации

В теле конструктора мы можем передать значения переменным класса. Однако константы требуют особого отношения. Например, вначале определим следующий класс:

class Person < const std::string name; unsigned age<>; public: void print() < std::cout Person(std::string p_name, unsigned p_age) < name = p_name; age = p_age; >>;

Этот класс не будет компилироваться из-за отсутствия инициализации константы name. Хотя ее значение устанавливается в конструкторе, но к моменту, когда инструкции из тела конструктора начнут выполняться, константы уже должны быть инициализированы. И для этого необходимо использовать списки инициализации :

#include class Person < const std::string name; unsigned age<>; public: void print() < std::cout Person(std::string p_name, unsigned p_age) : name  < age = p_age; >>; int main() < Person tom; tom.print(); // Name: Tom Age: 38 >

Списки инициализации представляют перечисления инициализаторов для каждой из переменных и констант через двоеточие после списка параметров конструктора:

Person(std::string p_name, unsigned p_age) : name

Здесь выражение name позволяет инициализировать константу значением параметра p_name. Здесь значение помещается в фигурные скобки, но также можно использовать кргулые:

Person(std::string p_name, unsigned p_age) : name(p_name)

Списки инициализации пободным образом можно использовать и для присвоения значений переменным:

class Person < const std::string name; unsigned age; public: void print() < std::cout Person(std::string p_name, unsigned p_age) : name(p_name), age(p_age) < >>;

При использовании списков инициализации важно учитывать, что передача значений должна идти в том порядке, в котором константы и переменные определены в классе. То есть в данном случае в классе сначала определена константа name, а потом переменная age. Соответственно в таком же порядке идет передача им значений. Поэтому при добавлении дополнительных полей или изменения порядка существующих придется следить, чтобы все инициализировалось в належащем порядке.

  • Глава 1. Введение в С++
    • Язык программирования С++
    • Первая программа на Windows. Компилятор g++
    • Первая программа на Windows. Компилятор Clang
    • Первая программа на Windows. Компилятор Microsoft Visual C++
    • Первая программа на Linux. Компилятор g++
    • Первая программа на MacOS. Компилятор Clang
    • Настройка параметров компиляции
    • Локализация и кириллица в консоли
    • Структура программы
    • Переменные
    • Типы данных
    • Константы
    • Ввод и вывод в консоли
    • using. Подключение пространств имен и определение псевдонимов
    • Арифметические операции
    • Статическая типизация и преобразования типов
    • Поразрядные операции
    • Операции присваивания
    • Условные выражения
    • Конструкция if-else и тернарный оператор
    • Конструкция switch-case
    • Циклы
    • Ссылки
    • Массивы
    • Многомерные массивы
    • Массивы символов
    • Введение в строки
    • Что такое указатели
    • Операции с указателями
    • Арифметика указателей
    • Константы и указатели
    • Указатели и массивы
    • Определение и объявление функций
    • Область видимости объектов
    • Параметры функции
    • Передача аргументов по значению и по ссылке
    • Константные параметры
    • Оператор return и возвращение результата
    • Указатели в параметрах функции
    • Массивы в параметрах функции
    • Параметры функции main
    • Возвращение указателей и ссылок
    • Перегрузка функций
    • Рекурсивные функции
    • Рекурсия на примере быстрой сортировки
    • Указатели на функции
    • Указатели на функции как параметры
    • Тип функции
    • Указатель на функцию как возвращаемое значение
    • Разделение программы на файлы
    • Внешние объекты
    • Динамические объекты
    • Динамические массивы
    • unique_ptr
    • shared_ptr
    • Определение классов
    • Конструкторы и инициализация объектов
    • Управление доступом. Инкапсуляция
    • Объявление и определение функций класса
    • Конструктор копирования
    • Константные объекты и функции
    • Ключевое слово this
    • Дружественные функции и классы
    • Статические члены класса
    • Деструктор
    • Структуры
    • Перечисления
    • Наследование
    • Управление доступом в базовых и производных классах
    • Скрытие функционала базового класса
    • Множественное наследование
    • Виртуальные функции и их переопределение
    • Преобразование типов
    • Динамическое преобразование
    • Особенности динамического связывания
    • Чистые виртуальные функции и абстрактные классы
    • Перегрузка операторов
    • Операторы преобразования типов
    • Оператор индексирования
    • Переопределение оператора присваивания
    • Пространства имен
    • Вложенные классы
    • Обработка исключений
    • Вложенные try-catch
    • Создание своих типов исключений
    • Тип exception
    • Типы исключений
    • Шаблоны функций
    • Шаблон класса
    • Специализация шаблона класса
    • Наследование и шаблоны классов
    • Типы контейнеров
    • Вектор
    • Итераторы
    • Операции с векторами
    • Array
    • List
    • Forward_list
    • Deque
    • Стек std::stack
    • Очередь std::queue
    • Очередь приоритетов std::priority_queue
    • Множества
    • Словарь std::map
    • Span
    • Определение строк
    • Строки с поддержкой Unicode
    • Преобразование типов и строки
    • Сравнение строк
    • Получение подстроки и проверка начала и конца строки
    • Поиск подстроки
    • Изменение строки
    • Операции с символами
    • Программа подсчета слов
    • Тип std:string_view
    • rvalue
    • Конструктор перемещения
    • Оператор присваивания с перемещением
    • Роль noexcept при перемещении
    • Объекты функций
    • Лямбда-выражения
    • Захват внешних значений в лямбда-выражениях
    • Шаблон std::function<>
    • Минимальный и максимальный элементы
    • Поиск элементов
    • Копирование элементов
    • Удаление элементов и идиома Remove-Erase Idiom
    • Сортировка
    • Представления. Фильтрация
    • Проекция данных
    • Пропуск элементов. drop_view и drop_while_view
    • Извлечение диапазона элементов. take_view и take_while_view
    • Цепочки представлений
    • Оператор requires
    • Концепты
    • Выражение requires
    • Ограничения типа для auto
    • Базовые типы для работы с потоками
    • Файловые потоки. Открытие и закрытие
    • Чтение и запись текстовых файлов
    • Переопределение операторов ввода и вывода
    • Математические константы и операции
    • Форматирование строк и функция format
    • std::optional
    • Управление ресурсами. Идиома RAII
    • Идиома копирования и замены
    • Идиома Move-and-Swap
    • Первая программа в Visual Studio
    • Первая программа в Qt Creator

    Как вызвать конструктор с параметром, для класса являющегося членом другого класса.

    Есть два класса c1 и c2 У каждого класса конструктор с параметром. Класс c1 является членом класса c2.

    class c1< int v; public: c1(int n);// конструктор класса c1 >; c1::c1(int n) < v=n; printf("Constructior c1.\n"); >class c2< int v; public: c2(int n); // конструктор класса c2 c1 e1; >; c2::c2(int n) < v=n; e1.c1(n); //пытаюсь вызвать конструктор класса c1, но не выходит printf("Constructior c2\n"); >int main(int argc,char **argv)

    При компиляции выдается сообщение о ошибке

    test.cpp: In constructor ‘c2::c2(int)’: test.cpp:29: error: no matching function for call to ‘c1::c1()’ test.cpp:17: note: candidates are: c1::c1(int) test.cpp:12: note: c1::c1(const c1&) test.cpp:31: error: invalid use of ‘class c1’ 

    Я так понимаю, что ошибка из за того, что конструктор вложенного класса имеет параметр. Вопрос. Как передать параметр конструктору члена класса?

    Mixaluch384
    04.11.11 23:08:48 MSK
    Последнее исправление: Mixaluch384 04.11.11 23:10:51 MSK (всего исправлений: 1)

    Как из одного конструктора вызвать другой конструктор в C++?

    При этом одновременно с вызовом другого конструктора нельзя вызывать конструкторы членов класса, например:

    struct B < B() : x(1) <>B(int x_) : B(), x(x_) <> // ОШИБКА: нельзя одновременно вызвать B() и x() int x; >; 

    Как только был вызван один из конструкторов, объект считается полностью сконструированным, по этому исключение из вызывающего конструктора приведет к вызову деструктора класса:

    struct C < C(const char*) < throw 1; >C() <> C(int) : C() < throw 1; >~C() < std::cout >; int main() < try < C c(""); // ничего не будет напечатано, деструктор не будет вызван >catch (. ) <> try < C c(1); // будет напечатано "~C" >catch (. ) <> > 

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *