在构造函数中反序列化 const 成员对象
Posted
技术标签:
【中文标题】在构造函数中反序列化 const 成员对象【英文标题】:Deserialize a const member object in a constructor 【发布时间】:2021-05-31 19:26:21 【问题描述】:我需要在构造函数中初始化类的 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<>()
通常被认为是一种不好的做法。我读到它主要是为了与不正确的旧 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
成员变量通常很痛苦,而且很少有用。
@TedLyngmo 我不希望它在构建后被修改。
没关系,但它是private
,所以任何东西都无法从课堂外修改它。
@TedLyngmo 好吧,我不希望它(无意中)被这个类的方法修改
@TedLyngmo 是的,我刚刚接受了你的回答。谢谢。
【参考方案1】:
只需将成员变量设为非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;
;
【讨论】:
以上是关于在构造函数中反序列化 const 成员对象的主要内容,如果未能解决你的问题,请参考以下文章