Base c что это
Перейти к содержимому

Base c что это

  • автор:

Что означает base в данном примере?

Что означает %k в данном случае?
#include <iostream> #include <conio.h> using namespace std; void main() < int i,j,k;.

Что означает pos ^= 1 в данном коде?
#include <stdio.h> #include <stdlib.h> #define FILE_NAME "numbers.txt" int.

Что в данном случае означает friend?
Всем доброй ночи! Помню, кода-то очень давно мельком видел, что кто-то уже спрашивал аналогичный.

Что означает символ t в данном вариативном шаблоне?
Полный код: #include <iostream> template <typename T> struct NameOf <>; #define.

610 / 415 / 151
Регистрация: 11.01.2019
Сообщений: 1,746

Лучший ответ

Сообщение было отмечено jongl как решение

Решение

base — имя переменной. Здесь определяется 3 переменных типа int: base, b, c. Переменная base получает начальное значение из некоторой переменной а (которая определена где-то выше по тексту), с инициализируется нулем. Про инициализацию b в таком контексте ничего не скажешь. Это может быть и нуль, и мусор (если локальный контекст).

Регистрация: 04.12.2020
Сообщений: 35

Хах, спасибо. Я так и думал, меня просто насторожило то, что в моём codeblocks base выделялся синим. Принял сначала как за обычную переменную, но потом начал мудрить и думать, что это какой то тип данных, или что ещё похуже.

87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
Помогаю со студенческими работами здесь

Не могли бы вы объяснить простыми словами что делают функции calloc в данном примере
Не могли бы вы объяснить простыми словами что делают функции calloc в данном примере? struct.

Что означает знак тильда в данном примере?
Что означает знак тильда в данном примере? $s = "Один 1 два 2 и три 3"; if ($s =~.

Что не так в данном примере
Добрый день. Можете подсказать что не так в данном примере, скорей всего не правильны написания.

Что означает this в данном контексте?
Привет дорогие киберфорумцы. Нашел код который меня поверг в замешательство. Вот от окаянный: .

Объектно-ориентированное программирование

Наследование (inheritance) является одним из ключевых моментов ООП. Благодаря наследованию один класс может унаследовать функциональность другого класса.

Пусть у нас есть следующий класс Person, который описывает отдельного человека:

class Person < private string _name = ""; public string Name < get < return _name; >set < _name = value; >> public void Print() < Console.WriteLine(Name); >>

Но вдруг нам потребовался класс, описывающий сотрудника предприятия — класс Employee. Поскольку этот класс будет реализовывать тот же функционал, что и класс Person, так как сотрудник — это также и человек, то было бы рационально сделать класс Employee производным (или наследником, или подклассом) от класса Person, который, в свою очередь, называется базовым классом или родителем (или суперклассом):

class Employee : Person

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

Таким образом, наследование реализует отношение is-a (является), объект класса Employee также является объектом класса Person:

Person person = new Person < Name = "Tom" >; person.Print(); // Tom person = new Employee < Name = "Sam" >; person.Print(); // Sam

И поскольку объект Employee является также и объектом Person, то мы можем так определить переменную: Person p = new Employee() .

По умолчанию все классы наследуются от базового класса Object , даже если мы явным образом не устанавливаем наследование. Поэтому выше определенные классы Person и Employee кроме своих собственных методов, также будут иметь и методы класса Object: ToString(), Equals(), GetHashCode() и GetType().

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

  • Не поддерживается множественное наследование, класс может наследоваться только от одного класса.
  • При создании производного класса надо учитывать тип доступа к базовому классу — тип доступа к производному классу должен быть таким же, как и у базового класса, или более строгим. То есть, если базовый класс у нас имеет тип доступа internal , то производный класс может иметь тип доступа internal или private , но не public . Однако следует также учитывать, что если базовый и производный класс находятся в разных сборках (проектах), то в этом случае производый класс может наследовать только от класса, который имеет модификатор public.
  • Если класс объявлен с модификатором sealed , то от этого класса нельзя наследовать и создавать производные классы. Например, следующий класс не допускает создание наследников:

sealed class Admin

Доступ к членам базового класса из класса-наследника

Вернемся к нашим классам Person и Employee. Хотя Employee наследует весь функционал от класса Person, посмотрим, что будет в следующем случае:

class Employee : Person < public void PrintName() < Console.WriteLine(_name); >>

Этот код не сработает и выдаст ошибку, так как переменная _name объявлена с модификатором private и поэтому к ней доступ имеет только класс Person . Но зато в классе Person определено общедоступное свойство Name, которое мы можем использовать, поэтому следующий код у нас будет работать нормально:

class Employee : Person < public void PrintName() < Console.WriteLine(Name); >>

Таким образом, производный класс может иметь доступ только к тем членам базового класса, которые определены с модификаторами private protected (если базовый и производный класс находятся в одной сборке), public , internal (если базовый и производный класс находятся в одной сборке), protected и protected internal .

Ключевое слово base

Теперь добавим в наши классы конструкторы:

class Person < public string Name < get; set;>public Person(string name) < Name = name; >public void Print() < Console.WriteLine(Name); >> class Employee : Person < public string Company < get; set; >public Employee(string name, string company) : base(name) < Company = company; >>

Класс Person имеет конструктор, который устанавливает свойство Name. Поскольку класс Employee наследует и устанавливает то же свойство Name, то логично было бы не писать по сто раз код установки, а как-то вызвать соответствующий код класса Person. К тому же свойств, которые надо установить в конструкторе базового класса, и параметров может быть гораздо больше.

С помощью ключевого слова base мы можем обратиться к базовому классу. В нашем случае в конструкторе класса Employee нам надо установить имя и компанию. Но имя мы передаем на установку в конструктор базового класса, то есть в конструктор класса Person, с помощью выражения base(name) .

Person person = new Person("Bob"); person.Print(); // Bob Employee employee = new Employee("Tom", "Microsoft"); employee.Print(); // Tom

Конструкторы в производных классах

Конструкторы не передаются производному классу при наследовании. И если в базовом классе не определен конструктор по умолчанию без параметров, а только конструкторы с параметрами (как в случае с базовым классом Person), то в производном классе мы обязательно должны вызвать один из этих конструкторов через ключевое слово base. Например, из класса Employee уберем определение конструктора:

class Employee : Person < public string Company < get; set; >= ""; >

В данном случае мы получим ошибку, так как класс Employee не соответствует классу Person, а именно не вызывает конструктор базового класса. Даже если бы мы добавили какой-нибудь конструктор, который бы устанавливал все те же свойства, то мы все равно бы получили ошибку:

class Employee : Person < public string Company < get; set; >= ""; public Employee(string name, string company) // ! Ошибка < Name = name; Company = company; >>

То есть в классе Employee через ключевое слово base надо явным образом вызвать конструктор класса Person:

class Employee : Person < public string Company < get; set; >= ""; public Employee(string name, string company) : base(name) < Company = company; >>

Либо в качестве альтернативы мы могли бы определить в базовом классе конструктор без параметров:

class Person < public string Name < get; set; >// конструктор без параметров public Person() < Name = "Tom"; Console.WriteLine("Вызов конструктора без параметров"); >public Person(string name) < Name = name; >public void Print() < Console.WriteLine(Name); >>

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

public Employee(string company)

Фактически был бы эквивалентен следующему конструктору:

public Employee(string company) :base()

Порядок вызова конструкторов

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

class Person < string name; int age; public Person(string name) < this.name = name; Console.WriteLine("Person(string name)"); >public Person(string name, int age) : this(name) < this.age = age; Console.WriteLine("Person(string name, int age)"); >> class Employee : Person < string company; public Employee(string name, int age, string company) : base(name, age) < this.company = company; Console.WriteLine("Employee(string name, int age, string company)"); >>

При создании объекта Employee:

Employee tom = new Employee("Tom", 22, "Microsoft");

Мы получим следующий консольный вывод:

Person(string name) Person(string name, int age) Employee(string name, int age, string company)

В итоге мы получаем следующую цепь выполнений.

  1. Вначале вызывается конструктор Employee(string name, int age, string company) . Он делегирует выполнение конструктору Person(string name, int age)
  2. Вызывается конструктор Person(string name, int age) , который сам пока не выполняется и передает выполнение конструктору Person(string name)
  3. Вызывается конструктор Person(string name) , который передает выполнение конструктору класса System.Object, так как это базовый по умолчанию класс для Person.
  4. Выполняется конструктор System.Object.Object() , затем выполнение возвращается конструктору Person(string name)
  5. Выполняется тело конструктора Person(string name) , затем выполнение возвращается конструктору Person(string name, int age)
  6. Выполняется тело конструктора Person(string name, int age) , затем выполнение возвращается конструктору Employee(string name, int age, string company)
  7. Выполняется тело конструктора Employee(string name, int age, string company) . В итоге создается объект Employee

C#. Доступ к элементам базового класса из унаследованного класса. Ключевые слова base, new. Примеры

Доступ к элементам базового класса из унаследованного класса. Ключевые слова base , new . Примеры

Поиск на других ресурсах:

1. Ключевое слово base . Назначение. В каких случаях используется ключевое слово base ?

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

Ключевое слово base используется в унаследованных классах в следующих случаях:

  • когда из конструктора производного класса нужно вызвать конструктор базового класса. Более подробно об этом способе использования base описывается здесь ;
  • когда из метода производного класса нужно вызвать метод базового класса, если этот метод переопределяется;
  • когда из метода производного класса нужно получить доступ к члену данных базового класса. В этом случае член данных может быть объявлен с любым модификатором доступа кроме private ;
  • когда из метода производного класса нужно получить доступ к свойству базового класса (свойство не объявлено как private );
  • если нужно подчеркнуть (конкретизировать), что в данном методе унаследованного класса используются элементы базового класса.
2. Вызов методов базового класса с помощью base . Общая форма. Пример

С помощью ключевого слова base можно обращаться к любым элементам базового класса, которые не являются скрытыми (не содержат модификатора private ).

Общая форма использования ключевого слова base для доступа к методу базового класса следующая:

base.Method();

где Method() – метод базового класса. Если в производном классе нет реализации метода с именем Method() , то использование base необязательно.

Общая форма использования ключевого слова base для доступа к члену данных (не private члену данных)

base.variable;

где variable – имя члена данных базового класса.

3. Графическое объяснение доступа к элементам с помощью ключевого слова base

На рисунке 1 демонстрируется доступ к элементам базового класса A из метода производного класса B .

C#. Наследование. Ключевое слово base. Способы доступа к разным элементам классов

Рисунок 1. Способы доступа к разным элементам классов A , B из метода Method()

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

Пусть заданы два класса A и B . Базовый класс A содержит следующие элементы:

  • внутреннее поле d с модификатором доступа protected ;
  • внутреннее поле a с модификатором доступа private ;
  • public -метод с именем Method1() ;
  • public -свойство AA , которое реализует доступ к внутреннему полю a .

Класс B наследует класс A и содержит следующие элементы:

  • внутреннее поле d с модификатором доступа protected ;
  • внутреннее поле b с модификатором доступа private ;
  • public-метод с именем Method1() ;
  • public-свойство BB , реализующее доступ к внутреннему полю b .

Демонстрационный текст программы, созданной по шаблону Console Application следующий

using static System.Console; namespace C_sharp < // Класс A - базовый для класса B class A < // 1. Внутренние поля класса protected int d; private int a; // 2. Конструктор класса public A() < // инициализирует поля некоторыми значениями a = 10; d = 20; > // 3. Общедоступный метод класса public void Method1() < WriteLine("A.Method1()"); > // 4. Общедоступное свойство - доступ к полю a public int AA < get < return a; > set < a = value; > > > // Класс B - унаследованный от класса A class B : A < // 1. Внутренние поля класса // Поле d перекрывает одноименное поле d класса A, protected int d; private int b; // 2. Конструктор класса public B() < d = 40; b = 50; >// 2. Метод, который перекрывает метод Method1() класса A, // в этом методе демонстрируется доступ // к разным элементам класса A public void Method1() < WriteLine("B.Method1()"); // 1. Обращение к методу Method1() класса A base.Method1(); // 2. Вызов свойства AA класса A int t = AA; // здесь можно без слова base WriteLine("A.AA = ", t); // 3. Доступ к внутреннему полю d класса A t = base.d; // поле d класса A WriteLine("A.t = ", t); // 4. Доступ к полю a класса A - запрещено // t = base.a; // запрещено, поле A.a есть private > // 3. Общедоступное свойство BB public int BB < get < return b; > set < b = value; > > > class Program < static void Main(string[] args) < // Демонстрация использования ключевого слова base // 1. Создать экземпляр класса B B obj = new B(); // 2. Вызвать метод Method1 класса B, // в этом методе используются элементы класса A objB.Method1(); > > >
5. Доступ к свойствам базового класса с помощью base . Пример базового класса Circle и производного класса Sector

В примере демонстрируется доступ к свойству базового класса. Заданы два класса: Circle – базовый класс, Sector – унаследованный класс от Circle . В обоих классах есть свойство Area . Чтобы из производного класса Sector вызвать свойство Area базового класса нужно обратиться следующим образом

base.Area;

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

using System; using static System.Console; namespace C_sharp < // Класс Circle - окружность class Circle < // 1. Внутренние поля protected double radius; // радиус protected double x, y; // координаты центра кола // 2. Конструктор public Circle(double _x, double _y, double _radius) < x = _x; y = _y; if (_radius else radius = _radius; > // 3. Свойства - доступ к внутренним полям класса public double X < get < return x; > set < x = value; > > public double Y < get < return y; > set < y = value; > > public double Radius < get < return radius; > set < if (value else radius = value; > > // 4. Свойство Area - возвращает площадь окружности public double Area < get < return Math.PI * radius * radius; > > > // Класс Sector - сектор (часть окружности) class Sector : Circle < // 1. Внутреннее поле protected double alpha; // угол сектора alpha = 0..360 // 2. Конструктор – вызывает конструктор базового класса Circle public Sector(double _x, double _y, double _radius, double _alpha) : base(_x, _y, _radius) < if ((_alpha >= 0) && (_alpha < 360)) alpha = _alpha; else alpha = 0.0; > // 3. Свойство для доступа к внутреннему полю public double Alpha < get < return alpha; > set < if ((value >= 0) && (value < 360)) alpha = value; else alpha = 0.0; > > // 4. Свойство, которое вычисляет площадь сектора // вызывает одноименное свойство базового класса public double Area < get < // Вызвать свойство базового класса return base.Area * alpha / 360; > > > class Program < static void Main(string[] args) < Sector sc = new Sector(1.5, 2.2, 3.0, 100); double x = sc.Area; // вывести площадь сектора WriteLine("Area of sector = ", x); > > >

Как видно из вышеприведенного кода, в базовом классе Circle реализовано свойство Area , которое используется в одноименном свойстве производного класса Sector следующим образом

. class Sector < . // 4. Свойство, вычисляющее площадь сектора, // вызывает одноименное свойство базового класса public double Area < get < // Вызвать свойство базового класса return base.Area * alpha / 360; > > > .
6. Необходимость применения ключевого слова new

Ключевое слово new может быть применено в унаследованном классе перед именем элемента, который перекрывает (скрывает) имя базового класса. Использование слова new рекомендуется компилятором в случае, когда нужно подчеркнуть, что именно данный метод или свойство переопределяют одноименный метод базового класса.
На рисунке 2 обозначено использование слова new для переопределения метода в производном классе.

C#. Наследование. Ключевое слово new при наследовании

Рисунок 2. Способы реализации метода Method() , который переопределяет одноименный метод базового класса

Если не указывать ключевое слово new в методе унаследованного класса, то это не повлияет на функциональность программы. Однако, в этом случае компилятор будет выдавать предупреждение:

B.Method hides inherited member A.Method. Use the new keywork if hiding was intended

Кроме того, компилятор предложит исправить эту неточность и, если нужно, сам установит ключевое слово new в нужном месте.

Связанные темы

  • Наследование. Базовые понятия. Преимущества и недостатки. Общая форма. Простейшие примеры. Модификатор доступа protected
  • Использование конструкторов в классах при наследовании. Ключевое слово base при наследовании

Developer notes

Рассмотрим элиминацию (оптимизацию) пустого базового класса на примере двух классов Foo и Bar:

Класс Foo является пустым. Как известно, размер любого объекта пустого класса как — минимум — равен 1 байту (для большинства компиляторов):

sizeof(Foo) == 1

Это достигается молчаливой вставкой компилятором одного байта (char) в такой пустой объект. Теперь посмотрим на размер класса Bar:

sizeof(Bar) == 2 * sizeof(int)

В данном случае объект класса Foo занимает 1 байт с выравниванием до размера члена i sizeof(int). Это связано с тем, что два базовых подобъекта одного типа должны иметь разные адреса.

Теперь организуем класс Bar с помощью наследования следующим образом:

class Bar : public Foo int i;
>;

И снова посмотрим на размер класса Bar:

sizeof(Bar) == sizeof(int)

В итоге мы видим, что компилятор при таком раскладе под подобъект Foo выделил 0 байт. В этом и состоит идея оптимизации пустого базового класса. В стандарте по этому поводу сказано:

A class with an empty sequence of [data] members and base class objects is an empty class. Complete objects and member subobjects of an empty class type shall have nonzero size.

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

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