Можно ли использовать конструктор копирования C ++ для других целей? - PullRequest
0 голосов
/ 06 июня 2018

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

В этой системе мне не нужно типичное значение копии объекта.Типичный конструктор копирования используется, когда объект передается по значению, возвращается по значению и ... Здесь в этой системе каждый объект уникален, поэтому нам не нужен типичный конструктор копирования.Два квадрата будут различаться как минимум для идентификатора.Поэтому я использую конструктор копирования для создания клонов.Во время клонирования я буду глубоко копировать древовидную структуру за исключением идентификатора.

#include <iostream>
#include <string>
#include <memory>
#include <cstdlib>
#include <vector>
int offset(){
    return rand()%100-50;
}
int location(){
    return rand()%10000-5000;
}
class Object2D{
public:
    int x_, y_;
    int id;
    static int count;
    Object2D(int x, int y):x_(x), y_(y){
        id=count++;
    }
};
int Object2D::count=0;
class Square: public Object2D{
public:
    int getParent(){return containedBy_->id;}
    Square(Object2D* containedBy, int size):
            Object2D(containedBy->x_+offset(), containedBy->y_+offset()),
            containedBy_(containedBy),size_(size){
        std::cout<<"Square constructor"<<std::endl;
    }
    Square(const Square& other):
            Object2D(other.x_-other.containedBy_->x_, other.y_-other.containedBy_->y_), 
            containedBy_(other.containedBy_), size_(other.size_){
        std::cout<<"Square clone"<<std::endl;
    }
private:    
    Object2D* containedBy_;
    size_t size_;
};
class Box:public Object2D{
private:
    size_t l_;size_t h_;
    std::vector<std::shared_ptr<Square>> all;
public:
    void addSquare(int size){
        auto temp = std::make_shared<Square>(this, size);
        all.push_back(std::move(temp));
    }
    const std::vector<std::shared_ptr<Square>>& getAll() const{
        return all;
    }
    Box(int x, int y, size_t l, size_t h):
            Object2D(x,y), l_(l), h_(h){}
    Box(const Box& other):Object2D(location(), location()){// clone the other box, put cloned squares in
        for(const auto& item:other.getAll()){
            all.push_back(std::make_shared<Square>(*item));
        }
    }
    void showOffsets(){
        std::cout<<"show offsets of all components for container"<<id<<":";
        for(const auto& item: all){
            std::cout<<item->id<<"("<<item->x_-x_<<","<<item->y_-y_<<")"<<" ";
        }
        std::cout<<std::endl;
    }
};

int main()
{
    Box b(100,100,100,100);
    std::cout<<"before do it"<<std::endl;

    b.addSquare(10);
    Box c(b);
    std::cout<<b.id<<c.id<<std::endl;

    b.showOffsets();
    c.showOffsets();
    return 0;
}

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

Вопрос

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

Во-вторых, почему смещения не копируются во время клонирования?Это то, что я хотел бы сохранить.

Результаты:

before do it
Square constructor
Square clone
02
show offsets of all components for container0:1(36,33) 
show offsets of all components for container2:3(-1879,2256) 

1 Ответ

0 голосов
/ 06 июня 2018

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

однако, как вы уже заметили, таким образом вам будет трудно "запрещать" копии там, где вы явно не хотите их копировать.

Мое предложение: дайте вашему объекту функцию clone() и delete конструктор копирования (возможно, также оператор копирования).

таким образом вы клонируете только тогда, когда вы явно намереваетесь.

...