【问题标题】:Force using implicit cast in assign opertor强制在赋值运算符中使用隐式强制转换
【发布时间】:2020-07-02 06:34:50
【问题描述】:

在下面的代码中,有什么方法可以强制编译器使用隐式强制转换为 bool(在 b3 = b2 赋值中)而不是生成复制赋值运算符而不使用强制转换运算符?不幸的是,在显式删除复制分配代码后没有构建。缺乏显式转换对我的框架很重要。

class Base
{
public :

   Base& operator=(const Base&) = delete;
   virtual Base& operator=(bool state) { state_ = state; }
   virtual operator bool() const { return state_; }
   virtual bool operator!() const { return !state_; }

protected :
   bool state_;
};

int main(void)
{
   Base b1, b2, b3;
   b1 = true;
   b2 = !b1;
   b3 = b2;

   return 0;
}

更新: 错误是

test.cpp: In function ‘int main()’:
test.cpp:20:9: error: use of deleted function ‘Base& Base::operator=(const Base&)’
    b3 = b2;
         ^~
test.cpp:6:10: note: declared here
    Base& operator=(const Base&) = delete;
          ^~~~~~~~

更新2: 正如@serge-ballesta 所说的基本赋值运算符就足够了

#include <iostream>

class Base
{
public :

   virtual Base& operator=(const Base &rhs) { std::cout << "BASE = BASE" << std::endl; return *this = static_cast<bool>(rhs); };
   virtual Base& operator=(bool state) { std::cout << "BASE = bool" << std::endl;  state_ = state; return *this; }
   virtual operator bool() const { return state_; }
   virtual bool operator!() const { return !state_; }

protected :
   bool state_;
};

class Derived :
   public Base
{
public :
   virtual Base& operator=(bool state) { std::cout << "DERIVED = bool" << std::endl; state_ = state; /* And something more */ return *this; }
};

int main(void)
{
   Base b1, b2, b3;
   b1 = true;
   b2 = !b1;
   b3 = b2;

   Derived d1, d2, d3, d4;
   d1 = true;
   d2 = !d1;
   d3 = d2;
   d4 = b3;

   return 0;
}

输出是:

BASE = bool      # b1 = true;
BASE = bool      # b2 = !b1;

BASE = BASE      # b3 = b2;
BASE = bool      # ditto

DERIVED = bool   # d1 = true;
DERIVED = bool   # d2 = !d1;

BASE = BASE      # d3 = d2;
DERIVED = bool   # ditto

DERIVED = bool   # d4 = b3;

有趣的是,在最后一种情况下,隐式转换是按照我的意愿完成的。

【问题讨论】:

  • 我不确定编译器是否会在没有显式转换的情况下尝试执行此操作...可能会通过多种不同类型进行任意数量的此类转换。
  • 如果你显式删除函数,那么不行,你不能这样做,错误会一直存在。
  • 根据定义,您不能强制编译器使用隐式强制转换。强制转换始终是显式的:它是您在源代码中编写的内容,用于告诉编译器进行转换。您要查找的术语是隐式转换
  • @PeteBecker 是的,这句话很不幸 - 我的意思是使用隐式转换来指导编译器 -> 带有转换值的运算符

标签: c++ operator-overloading


【解决方案1】:

明确删除分配运算符意味着您希望类不可复制。在这里,您只希望复制分配使用布尔转换:

Base& operator=(const Base& other) {
    *this = static_cast<bool>(other);
    return *this;
}

不幸的是,您将不得不重写派生类中的赋值运算符以强制使用这个:

class Derived: public Base {
public:
    Derived& operator=(Derived& other) {
        Base::operator = (other);
        return *this;
    }   
    ...
};

【讨论】:

  • 问题是对于来自Base的每个派生类我都需要再次定义这个函数...
  • 好吧,我认为你是对的,我会在更新中告诉更多内容
  • @cdhowie:不幸的是,即使使用虚拟运算符,该类的默认赋值运算符也具有更高的优先级,除非它被覆盖。在我的测试中,除非我覆盖赋值运算符,否则会复制派生类中的其他字段。
  • 我做了一些测试(见更新), virtual operator=(Base &) 就足够了,不需要创建新的,问题是这个解决方案的便携性如何......
  • @Nabuchodonozor:我用一个相当旧的 CLang 版本进行了测试。可能是 C++ 版本级别的问题...
猜你喜欢
  • 1970-01-01
  • 2020-05-16
  • 2018-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多