Представим
себе ситуацию, что я создал класс А и в нем два обЪекта w и v, а так же написана функция
void col(const А & v) этого класса,класс устроен таким образом, что в нем есть
приватный double x.
Вопрос
в следующем, пусть я нахожусь в функции
w.col()
{
могу ли я здесь, внутри определения функции
обращаться к приватным данным обЪекта v?
например, v.х=...
}
Конечно, нет. К приватным объектам можно обращаться только если Вы находитесь внутри типа (типа, а не объекта), для которого эти объекты являются приватными. Т.е. так нельзя:
class A{int
x;};
class C{ A x; C(){x.x=0;}};
Можно только так:
class C{ int x; C(){x=0;}};
либо так:
class C{ int x; void f(){C q; q.x=0;}};
либо так:
class C{ int x; void f();};
void C::f(){C q; q.x=0;}
Измениться
ли ситуация, если в предыдущем вопросе в его условии сделать замену( col(const
A & v) ) ->( col(const
A v) )?
Как уже было сказано, не поможет.
Представим
себе ситуацию, что я создал класс А и в нем обЪект w , а так же
написана функция
A col() этого класса,класс
устроен таким образом, что в нем есть приватный double
x.
Вопрос
в следующем, пусть я нахожусь в функции
w.col()
{Создаю здесь обЪект
класса А(A r;)
могу ли я здесь, внутри определения функции,где создал обЪект того же класса r,
обращаться к приватным данным обЪекта r?
например, r.х=...
return r;
}
Как уже говорилось, так можно.
Чем
отличается конструктор копирования от присвоения?
Конструктор
копирования (как и любой конструктор) – первое, что случается в жизни объекта.
До этого не было ничего. Оператор присваивания вызывается
когда объект уже прожил некоторую жизнь. Т.е. какие-то ресурсы в нем могут быть
отведены.
Во время присвоения включается ли конструктор
копирования?
Конечно,
нет.
Передача обЪекта в
функцию НЕ по ссылке происходит через конструктор копирования?
Да. При
передаче параметра по значению формальный параметр создается с помощью
конструктора копирования из фактического параметра.
Вы говорили, что конструктор и деструктор
всегда существуют по умолчанию,
правильно ли я понимаю, что конструктор
копирования всегда существует и по
умолчанию это просто побитовое копирование обЪекта,который мы отправляем,
в обЪект,который
создается во время вызова функции(локальный обЪект)?
Да.
Я не
совсем понимаю, как возвращается значение из функции и ее
вызов,
я
изложу, как я это понимаю,и
если это неверно, подскажите пожалуйста где.
В
момент когда в исполнительном файле встречается вызов функции,исполнение передается по адресу,
где
определен код этой функции(при этом запоминается адрес
места,с которого было снято исполнение),
а так
же создаются внутренние временные переменные они называются формальные параметры
соответствующих
типов и с помощью конструктора
копирования
в них копируются отправляемые данные они
называются фактические параметры (я рассматриваю случай отправления аргументов
по значению,без ссылок).
Когда
исполнение переходит по адресу функции,в
ней выделяется память под переменные(аргументы) и они инициализируются
с
помощью конструктора копирования,который
побитово копирует в них отправляемые в нее значения
(данные).
Да
(После
этого ранее создаваемые временные переменные уничтожаются)
А это о чём?
Ведь в функции ничего ранее не создавалось!
Потом
исполняется код этой функции,и
во время окончания работы и возвращения значения,
опять
же создается временная переменная, в которую с помощью конструктора копирования
помещается возвращаемое
значение,функция
заканчивает работу(удаляет все локальные переменные )
и
возвращается по адресу,с которого
исполнение было снято,неся с собой значение,
хранящееся в этой временной переменной, потом с ней могут выполняться некоторые
манипуляции,например,если
функция была вызвана во время выполнения оператора
сложения,или она
стояла в качестве вычисляемого выражения,а затем эта
временная переменная удаляеться.
Вы описали поведение, которое я называю стандартным. Оно мне нравится. Так происходит в Microsoft если компилировать файлы без оптимизации. Так происходит в gcc с ключом -fno-elide-constructors
Если же в Microsoft компилировать файлы с оптимизацией или в gcc без ключа -fno-elide-constructors, то все происходит не так: переменная, которую Вы возвращаете в return, просто используется снаружи функции. А уничтожается она после завершения всего оператора, в котором вызывается данная функция.
Я
читал книгу по С++(пытался), и в ней часто говорилось,
что заинклюдить фразу
using namespace std; является злом и очагом «сгорания программы»,не могли бы обЪяснить ,
чем это могло быть вызвано?
Очевидно, фраза using namespace std; фактически включает все содержимое пространства имен в данное место (по крайней мере, описаний). А включаться там может много чего. Include-файл может многократно включаться в один cpp-файл, что приведет к замедлению компиляции и увеличению ресурсов, которые требует компилятор. Для небольших программ это непринципиально. Если честно, я не знаю, является ли это принципиальным для больших программ.
Если найдете другое объяснение – напишите обязательно.
Я
пытался сделать без using
namespace std; но почему-то
выскакивала ошибка
с std::ostream, хотя я думал ,что она из пространства имен std::,
я написал без
нее,ошибка осталась?
Класс ostream описывается в #include <iostream>
Для ostream не нужен namespace.
С помощью namespace становится доступной переменная cout
Как ,например, в классе комплексных чисел реализовать фигурную
инициализацию для массивов и возможно ли это вообще?
CComplex[2]={(1,2),(2,3)}-чтобы вот так
реализовывать…
По сути, Вы спрашиваете, можно ли делать так:
#include <iostream>
class CComplex
{
double a,b;
public:
CComplex(){a=b=0;}
CComplex(double
a,double b){this->a=a;this->b=b;}
};
CComplex operator()(double a,double
b){return CComplex(a,b);}
int main(void)
{ CComplex m[2]={(1.,2.),(3.,4.)};
}
Ответ: нет, так делать нельзя. operator() может быть только методом класса. Почему – отдельный вопрос. Думаю, ответ на него скрыт где-то в семантике языка.