我见过一个CRTP解决方案,它将接口提取到基类中,并且只为每个基类提供一个包参数.然后,派生程度最高的类继承了所有friended基类并实现了接口.
我不能使用这种方法,因为我需要保护赋值运算符,它不是继承的.
此外,由于赋值运算符具有仅具有一个参数的已定义签名,因此我无法使用密钥模式.
这就是我想要的:
template <typename... F>
struct A {
protected:
A& operator=(const SomeClass &other) {
//...
}
private:
//I would like to do the following, but it does not work
friend F...;
}
Run Code Online (Sandbox Code Playgroud)
有办法做我需要的吗?
我有一个 getter,它返回一个临时对象,即内部对象的副本。
类似于以下内容:
class Foo
{
public:
QString name() {return m_name;}
void setName(const QString &name);
private:
QString m_name;
}
Run Code Online (Sandbox Code Playgroud)
setter/getter 的预期用途是获取数据name()并通过设置数据setName()。
但有时,错误地,我倾向于执行以下操作:
name().clear();
Run Code Online (Sandbox Code Playgroud)
或者直接对 getter 的返回进行一些其他修改。
请注意,上述行(以及类似的修改)的目的是清除 Foo,而不是临时变量,因此上面的行可以正确编译,但行为不正确,因为它将清除临时成员,而不是 Foo 的成员。
如何禁用这种不正确的用法,并在编译时出错?
请注意,我可能同时拥有第三方类型(我无法修改,例如 std::string 或上面的 QString)和自定义类型(我可以为此修改)。
编辑:
需要注意的是超载const,&,&&或类似的是没有用的,因为我可能是这样的:
Foo foo;
foo.name().clear();
Run Code Online (Sandbox Code Playgroud)
无论您选择什么重载,它都会编译得很好。
此外,对内部成员的所有修改都必须经过setName(),因为它会应用一些逻辑并通知其他一些对象,因此必须避免任何不是通过接口进行的修改。这可以防止 getter 通过非常量引用返回以允许上述用法或将私有成员设为公共成员。