생성자에서 클래스의 const 멤버 개체를 초기화해야하지만 멤버의 생성자는 빈 개체 만 생성하는 반면 실제 초기화는 파일에서이 개체를 역 직렬화하여 수행해야합니다. 멤버 개체의 클래스는 내 것이 아니므로 변경할 수 없습니다. 즉, Dlib 모델이며 다음 코드는 동작을 시뮬레이션합니다.
#include <iostream>
#include <string>
// not my class, can't be changed
class ShapePredictor
{
friend std::istream& operator >> (std::istream& stream, ShapePredictor&);
public:
ShapePredictor() = default;
ShapePredictor(const ShapePredictor& other) : data(other.data) { std::cout << "copy" << std::endl; }
ShapePredictor(ShapePredictor&& other) : data(std::move(other.data)) { std::cout << "moved" << std::endl; }
private:
std::string data;
};
// deserialization
std::istream& operator >> (std::istream& stream, ShapePredictor& sp)
{
sp.data = "test33";
return stream;
}
class FaceExtractor
{
public:
FaceExtractor()
{
std::cin >> this->sp; // won't compile
}
private:
const ShapePredictor sp;
};
int main(int argc, char* argv[])
{
FaceExtractor extractor;
return 0;
}
최선의 방법이 무엇인지 잘 모르겠습니다. 가장 먼저 떠오르는 것은 다음을 사용하는 것입니다 const_cast<>()
.
class FaceExtractor
{
public:
FaceExtractor()
{
std::cin >> const_cast<ShapePredictor&>(this->sp);
}
private:
const ShapePredictor sp;
};
작동하지만 사용 const_cast<>()
은 일반적으로 나쁜 습관으로 간주됩니다. 나는 그것이 대부분 const 정확하지 않은 레거시 API와의 호환성을 위해 설계되었다고 읽었습니다. 제 경우에 사용하는 것이 괜찮을지 잘 모르겠습니다.
이 문제를 해결하는 또 다른 방법 deserialize()
은 클래스를 임시 객체에로드하고 반환 하는 멤버 함수를 만드는 것입니다.
class FaceExtractor
{
public:
FaceExtractor()
: sp(deserialize())
{ }
ShapePredictor deserialize()
{
ShapePredictor tmp;
std::cin >> tmp;
return tmp;
};
private:
const ShapePredictor sp;
};
여기에는 바람직하지 않은 임시 생성이 포함됩니다. 바라건대 NRVO는 사본을 제거하지만 MSVC에서는 여전히 한 번의 추가 이동 비용이 듭니다.
그런 종류의 객체를 초기화하는 일반적인 관행이 무엇인지 궁금합니다.
멤버 변수를 비 const
. const
멤버 변수 를 갖는 것은 일반적으로 고통스럽고 거의 유용하지 않습니다.
반드시 있어야한다면 const
에서 상속하는 클래스를 만들고 ShapePredictor
스트리밍을 수행하는 생성자를 추가 할 수 있습니다.
struct ShapePredictorStreamable : public ShapePredictor {
ShapePredictorStreamable(std::istream& is) {
is >> *this;
}
};
class FaceExtractor {
public:
FaceExtractor() : sp(std::cin) {}
private:
const ShapePredictorStreamable sp;
};
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다