繁体   English   中英

用 const 成员替换某个类型的变量

[英]Replace a variable of a type with const members

假设我有一个带有一些常量成员的类:

class MyClass {
public:
   MyClass(int a) : a(a) {
   }
   MyClass() : MyClass(0) {
   }
   ~MyClass() {
   }
   const int a;
};

现在我想在某处存储MyClass的实例,例如作为全局变量或作为另一个对象的属性。

MyClass var;

后来,我想给var赋值:

var = MyClass(5);

显然,这行不通,因为调用了赋值运算符,默认情况下不存在,因为MyClass有一个 const 属性。 到现在为止还挺好。

我的问题是,无论如何我如何为var赋值? 毕竟, var本身并没有被声明为常量。

到目前为止我的想法

我知道如果我对var使用指针,则问题不存在:

MyClass *var;
var = new MyClass(5);

但是,出于方便的原因,我不想使用指针。

一个潜在的解决方案是用placement new 覆盖内存:

template<class T, class... Args>
T &emplaceVar(T &myVar, Args&&... args) {
   myVar.~T(); // free internal memory
   return *new (&myVar) T(args...);
}

emplaceVar(var, 5);

这将解决问题,但我不确定这是否会导致内存泄漏或由于我缺乏 C++ 经验而没有想到的任何其他问题。 此外,我会认为必须有一种更简单的方法。 有没有?

由于您发现的原因, const成员通常有问题。

更简单的选择是将成员设为private并注意不要提供从类外部修改它的方法:

class MyClass {
public:
   MyClass(int a) : a(a) {
   }
   MyClass() : MyClass(0) {
   }
   ~MyClass() {
   }
private:
   int a;
};

我还没有添加 getter,因为你说通过myObject.a访问是一个硬性要求。 启用它需要一些样板文件,但它比修改一些不能修改的东西要少得多:

class MyClass {
public:
   struct property {
       const int& value;
       operator int(){ return value;}
       property(const property&) = delete;
   };

   MyClass(int a = 0) : value(a) {}
private:
   int value;
public:
    property a{value};
};

int main(){
    MyClass myObject{5};
    int x = myObject.a;
    //myObject.a = 42; // error
    //auto y = myObject.a; // unexpected type :/
}

现场演示

缺点是它不能很好地与auto 如果您可以通过任何方式接受myObject.a()我建议使用它并保持简单。

无论如何,我如何为 var 赋值?

您可以使用用户定义的赋值运算符来做到这一点:

class MyClass {
public:
   MyClass &operator=(const MyClass &o)
   {
         // Implement your assignment here

         return *this;
   }

   // ...
};

您的赋值运算符可以做任何operator=重载可以做的事情。 它唯一不能做的就是为它的const类成员分配任何东西。 那是因为它是恒定的。

如果一个类没有用户定义的赋值运算符,则默认赋值运算符从被赋值对象的同一成员中分配被赋值对象的每个成员。 然而,默认赋值运算符会从任何具有const成员的类中删除,因为这当然不再可能。

在您的用户定义运算符中,您可以做任何事情来从另一个对象分配这些对象之一。 它唯一不能做的事情与任何其他类方法都不能做的事情是一样的:修改const类成员。

您提到了析构函数的手动调用和新的放置。 这是可能的,前提是满足所有必要的要求并且小心避免未定义的行为。 但是,从技术上讲,这不是赋值,而是手动销毁和构建另一个对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM