В моем классе есть метод const, который должен выполнять копию экземпляра, чтобы сохранить оригинал постоянным (возможно, это можно считать плохим дизайном, но это другое обсуждение).
Было бы полезно скопировать только те переменные-члены, которые мне нужны для моей функции, а не все. Я хотел бы сделать именно это, но я также хотел бы использовать методы в моем скопированном экземпляре.
Вот почему я придумал частный конструктор копирования, который копирует только то, что мне нужно для методов, которые я использую в функции.
Примечание. Я вынужден использовать конструктор, потому что в моем классе есть члены, которые могут быть инициализированы только списком инициализаторов, то есть константными переменными, ссылками, конструкторами базового класса и т.д.
Я придумал этот конструктор, который очень похож на конструктор копирования, но принимает в качестве входных данных фиктивную переменную, чтобы компилятор знал, какую из них вызывать:
#include <ctime>
class MyClass {
public:
MyClass(const MyClass& other);
clock_t pure_func() const;
void messy_method();
private:
struct ForPureFunc {};
MyClass(const MyClass& other, ForPureFunc);
};
Вот реализация возможного метода, не имеющего побочных эффектов (имейте в виду, что это всего лишь пример):
clock_t MyClass::pure_func() const {
/*
lets say I want to time
the messy method
*/
MyClass copy(*this, ForPureFunc());
clock_t start = clock();
for (int i = 0; i < 10000; ++i)
copy.messy_method();
return clock() - start;
}
Я хотел спросить, сталкивался ли кто-нибудь с чем-то подобным, является ли передача фиктивной переменной используемой и хорошей техникой.





Одно из возможных решений, о котором я подумал, это:
class MyClass {
public:
MyClass(const MyClass& other);
private:
class SpecificCopy {
public:
SpecificCopy(const MyClass&);
// only the needed members
};
// other members
};
MyClass имеет член типа SpecificCopy?
Это не нужно, функция, которая хочет упрощенную копию, имеет объект этого пользовательского типа, инициализированный *this
Я понимаю, что ваш код просто пример, хотя я не понимаю, для чего. Обратите внимание, что MyClass(const MyClass& other, int) не является конструктором копирования. Конструктор копирования — это MyClass(const MyClass&) не что-то другое. Это различие важно, потому что в большинстве случаев конструктор копирования вызывается неявно, когда вы делаете копию:
void foo(Example);
Example a;
Example b = a; // calls the copy constructor
foo(b); // calls the copy constructor
MyClass(const MyClass& other, int) не является конструктором копирования. Если вас это устраивает, то ок. Это просто не конструктор, который будет вызываться неявно при создании копии.
Я знаю, что передача фиктивной переменной — это тот же процесс для перегрузки оператора префикса и постфикса ++:
Использование разрешения перегрузки — хорошая идея. Хотя такого эффекта, как с ++, вы не получите. ++ нужна специальная языковая поддержка, чтобы различать operator++() и operator++(int). Ваш конструктор не может получить эту поддержку.
Я не совсем уверен, хотите ли вы оставить некоторые элементы неинициализированными. Вы не должны этого делать. Лучше пересмотрите свой дизайн. Если MyClass делает больше, чем вам нужно в определенных местах, то это запах дизайна. Очень вероятно, что MyClass делает слишком много для одного класса (см. принцип единой ответственности).
Однако, если вам нужен конструктор, который делает какое-то копирование, доступное только для одной функции, вы можете сделать это:
#include <iostream>
struct MyClass;
void foo(MyClass&);
struct Proxy {
MyClass& object;
private:
Proxy(MyClass& object) : object(object) {}
friend void foo(MyClass&);
};
struct MyClass {
MyClass() = default;
MyClass(const Proxy& p) {} // implement special copy here
MyClass(const MyClass&) = default; // copy constructor
};
void foo(MyClass& a) {
MyClass b = Proxy(a);
}
int main() {
MyClass a;
MyClass b = Proxy(a); // fails to compile
}
Обратите внимание, что foo получает доступ только к MyClass(const Proxy& p), но не к каким-либо личным частям, которые могут быть у MyClass.
Комментарии перемещены в чат ; пожалуйста, не продолжайте обсуждение здесь. Прежде чем публиковать комментарий под этим, пожалуйста, ознакомьтесь с целями комментариев . Комментарии, которые не требуют разъяснений или предложений по улучшению, обычно относятся к ответу , к Meta Stack Overflow или в чату переполнения стека. Комментарии, продолжающие обсуждение, могут быть удалены.