Не могу разобраться, как прописать классу дружественную функцию из другого класса. Проблема в том, что классы написаны в разных файлах. Вот код:
// файл Complex.h
#include "Float.h"
class Complex
{
private:
Float Re, Im;
public:
Complex(Float re, Float im);
void readFloat(Float);
};
// файл Complex.cpp
#include "Complex.h"
#include
Ответ
Не получается потому, что для объявления дружественного метода требуется полное определение Complex, ведь вы обращаетесь к его члену.
Самый простой вариант - сделать другом не метод, а весь класс Complex
// файл Float.h
class Float
{
private:
float Num;
public:
Float(float num);
friend class Complex;
};
Если, всеж таки, необходим именно дружественный метод, тогда нужно обеспечить чтобы полное определение Complex гарантированно происходило до определения Float. Это можно сделать, применив технику с предварительным объявлением (forward declaration) Float в файле Complex.h:
// файл Complex.h
// #include "Float.h" // этот инклюд нужно убрать
class Float; // предварительное объявление
class Complex
{
private:
Float * Re;
Float * Im;
public:
Complex(Float & re, Float & im);
~Complex();
void readFloat(Float &);
};
// файл Complex.cpp
#include
#include "Complex.h"
#include "Float.h" // а здесь он нужен
void Complex::readFloat(Float&)
{
std::cout << "Чтение из дружественной функции: " << Re.Num;
}
// файл Float.h
#include "Complex.h" // мы обращаемся к членам Complex
// поэтому он должен быть объявлен заранее
class Float
{
private:
float Num;
public:
Float(float num);
friend void Complex::readFloat(Float&);
};
Техника работает следующим образом. Так как в файле Complex.h используются только указатели и ссылки на Float компилятору для вычисления размеров этих переменных и полей не требуется полное определение класса Float. Ведь размер указателей и ссылок фиксированный и заранее известен, вне зависимости от того, на что они указывают или ссылаются. Компилятору нужно только намекнуть что понимается под именем Float то есть что он класс, а не структура например. Компилятор не может работать с неизвестными именами. Из-за этой тонкости, можно убрать #include "Float.h" из файла Complex.h. Однако, когда мы обращаемся к членам Float необходимо его полное определение, поэтому в файле Complex.cpp обязательно наличие #include "Float.h". После всего этого можно безопасно добавлять #include "Complex.h" в файле Float.h.
В результате всех этих манипуляций получается, что класс Complex всегда определен до Float, хотя объявлен Float раньше Complex. Ну и в итоге, как вы помните, строгий порядок определений классов позволяет нам законно объявить дружественным метод Complex::readFloat.
Комментариев нет:
Отправить комментарий