Как прописать инициализацию объекта класса, у которого атрибут является объектом другого класса?

Рейтинг: 1Ответов: 1Опубликовано: 09.03.2023

Необходимо прописать инициализацию векторного пространства.

Для начала я прописал класс точка таким образом:

class point{
private:
    double x;
    double y;
    double z;
public:
    point(double value_x, double value_y, double value_z){
        x = value_x;
        y = value_y;
        z = value_z;
    }
    double get_point_x() const{
        return x;
    }
    double get_point_y() const{
        return y;
    }
    double get_point_z() const{
        return z;
    }
    void get_coord() const{
        cout << x << ' ' << y << ' ' << z;
    }
    void add(point point1, point point2){
        x = point1.x + point2.x;
        y = point1.y + point2.y;
        z = point1.z + point2.z;
    }
    void sub(point point1, point point2){
        x = point1.x - point2.x;
        y = point1.y - point2.y;
        z = point1.z - point2.z;
    }
    void mul(point point, double c){
        x = point.x * c;
        y = point.y * c;
        z = point.z * c;
    }
    void div(point point, double c){
        if (c == 0) exit(0);
        x = point.x / c;
        y = point.y / c;
        z = point.z / c;
    }
    static double distance(point point1, point point2){
        return sqrt(pow(point2.x - point1.x, 2) + pow(point2.y - point1.y, 2) + pow(point2.z - point1.z, 2));
    }
};

Далее я прописал класс вектор:

class vector{
private:
    double x;
    double y;
    double z;
public:
    vector(point point){
        x = point.get_point_x();
        y = point.get_point_y();
        z = point.get_point_z();
    }
    void get_coord() const{
        cout << x << ' ' << y << ' ' << z;
    }
    double get_length(vector vec){
        return sqrt(pow(vec.x, 2) + pow(vec.y, 2) + pow(vec.z, 2));
    }
    double get_vector_x() const{
        return x;
    }
    double get_vector_y() const{
        return y;
    }
    double get_vector_z() const{
        return z;
    }
    void add(vector vec1, vector vec2){
        x = vec1.x + vec2.x;
        y = vec1.y + vec2.y;
        z = vec1.z + vec2.z;
    }
    void sub(vector vec1, vector vec2){
        x = vec1.x - vec2.x;
        y = vec1.y - vec2.y;
        z = vec1.z - vec2.z;
    }
    void div(vector vec, double c){
        if (c == 0) exit(0);
        x = vec.x / c;
        y = vec.y / c;
        z = vec.z / c;
    }
    void num_mul(vector vec, double c){
        x = vec.x * c;
        y = vec.y * c;
        z = vec.z * c;
    }
    static double scal_mul(vector vec1, vector vec2){
        return vec1.x * vec2.x + vec1.y * vec2.y + vec1.z * vec2.z;
    }
    void vec_mul(vector vec1, vector vec2){
        x = vec1.y * vec2.z - vec1.z * vec2.y;
        y = vec1.x * vec2.z - vec1.z * vec2.x;
        z = vec1.x * vec2.y - vec1.y * vec2.x;
    }

};

Однако у меня возникли неприятность при написании векторного пространства:

class vector_space {
private:
    point o;
    vector v1;
    vector v2;
    vector v3;
public:
    vector_space(point point, vector vec1, vector vec2, vector vec3){
        o = point;
        v1 = vec1;
        v2 = vec2;
        v3 = vec3;
    }
};

Такая инициализация не работает и я не знаю, что дальше делать.

Ответы

▲ 3

Для каждого класса компилятор автоматически генерирует конструктор по умолчанию, конструктор копирования, конструктор перемещения, оператор присваивания. Но этого не происходит, если вы определили свои конструкторы. Это ваш случай. Каждый из ваших классов будет иметь только один конструктор - тот, который написали вы.

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

point& operator= (const point& other)
{
    // проверка на самоприсваивание
    if (this == &other)
        return *this;
    x = other.x; // Почленное копирование
    y = other.y;
    z = other.z;    

    // возвращаем существующий объект,
    // можно было включить этот оператор в цепочку
    return *this;
}

После определения этого оператора присваивание станет возможным. Но этот оператор используется только для уже существующего объекта! То есть объект, который находится слева от оператора присваивания, и объект, который находится справа от оператора присваивания, к моменту присваивания уже должны быть сконструированы (неважно, каким конструктором). Члены класса инициализируются конструктором по умолчанию до входа в тело конструктора. То есть вот здесь

vector_space(point point, vector vec1, vector vec2, vector vec3){
    o = point;
    v1 = vec1;
    v2 = vec2;
    v3 = vec3;
}

компилятор пытается сгенерировать код для конструирования объектов o, v1, v2, v3 до входа в тело конструктора. И это у него не получается, так как конструктор по умолчанию отсутствует. Если же требуется инициализировать члены класса каким-либо другим конструктором (не конструктором по умолчанию), то применяют member initializer lists. Например, так:

vector_space(point point, vector vec1, vector vec2, vector vec3) :
    o(1, 2, 3),  // вызовет определённый вами конструктор класса point
    v1(1, 2, 3), 
    v2(1, 2, 3),
    v3(1, 2, 3)
{
    o = point;
    v1 = vec1;
    v2 = vec2;
    v3 = vec3;
}

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

point(const point &other) {
    x = other.x;
    y = other.y;
    z = other.z;
}

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

class point{
private:
    double x;
    double y;
    double z;
public:
    point(double value_x, double value_y, double value_z){
        x = value_x;
        y = value_y;
        z = value_z;
    }
    point(const point &other) {
        x = other.x;
        y = other.y;
        z = other.z;
    }
    double get_point_x() const{
        return x;
    }
    double get_point_y() const{
        return y;
    }
    double get_point_z() const{
        return z;
    }
};

class vector{
private:
    double x;
    double y;
    double z;
public:
    vector(point point){
        x = point.get_point_x();
        y = point.get_point_y();
        z = point.get_point_z();
    }
    vector(const vector &other)
    {
        x = other.x;
        y = other.y;
        z = other.z;
    }
};

class vector_space {
private:
    point o;
    vector v1;
    vector v2;
    vector v3;
public:
    vector_space(point p, vector vec1, vector vec2, vector vec3) :
        o(p),
        v1(vec1),
        v2(vec2),
        v3(vec3)
    {
    }
};