有没有办法在重载的运算符功能中达到默认的运算符功能?

时间:2019-07-02 11:50:22

标签: c++

我想用重载包装操作符函数以用于调试。

例如:我想计算在为Foo对象运行程序期间完成了多少次操作。

static int counter = 0;
Foo operator=(const Foo& b) 
{
    //Somehow call default functionality of = opreator for foo.

    counter++;
}

在重载运算符时是否可以仅调用运算符的默认功能。就像编写覆盖函数时调用覆盖函数的基本函数一样。

4 个答案:

答案 0 :(得分:2)

如果使用“默认运算符功能”,则表示您希望operator=()进行简单完成的所有操作

Foo &operator=(const Foo &) = default;

但是,另外,要增加一个计数器,则没有直接的方法,因为这样的运算符只能有一个定义。

但是,通过使用类似的方法,您可以达到类似的效果

class Counter
{
     public:

          Counter &operator=(const Counter &) {++counter; return *this;};

          static int Count() {return counter;};
     private:
          static int counter;
};

并且(在一个完全可以看到类Counter定义的编译单元中,例如,通过包含包含类定义的标头即可)

int Counter::counter = 0;

然后只需添加一个Counter作为类Foo的私有非静态成员。这样,类operator=()中每次使用“默认” Foo都会使Counter::counter递增。

如果您的班级Foo是唯一使用Counter的地方,则以上内容将允许计算分配Foo的次数。任何时候需要做的就是调用Counter::Count()

正如Caleth在评论中所指出的,类Counter可以在类型上进行模板化,因此可以建立Foo与其他类的不同计数器。这也为使用CRTP(好奇地重复模板模式)打开了大门,其中Foo可以从Counter<Foo>派生而来,以提供所需的功能。

需要注意一些潜在的警告;

  • Counter的大小将为非零值,因此Foo的大小可能会发生变化。
  • 您将需要确保类Counter的构造函数和析构函数 (无论如何定义)都可以与Foo一起正常使用;
  • 如果Counter::count溢出,则行为将不确定 (用于限制您可以分配课程的次数);
  • 没有什么可以阻止其他代码的实例化和分配 Count,这会弄乱您的人数(尽管这种可能性 如果Counter具有所有成员private并将类Foo指定为friend,则可能会缓解(请注意,我没有说“反”)。

答案 1 :(得分:1)

如果提供自定义的operator=实现,则编译器不会生成默认的实现。无法访问它,因为它不存在。

我建议使用重载的operator=来创建一个单独的类,并将其作为字段(或基类)添加到class Foo中。

答案 2 :(得分:1)

这是一种引入基于模板的赋值运算符的方法,该运算符不会重载默认的赋值运算符:

static int counter;
struct Foo
{
    template<bool=false> Foo& operator=(const Foo& b)
    {
        // The non-debug one
        return operator=(b);
    }
    template<> Foo& operator=<true>(const Foo& b)
    {
        // The debug one
        ++counter;
        return operator=(b);
    }
};

然后您就可以使用

Foo f;
Foo g;
g.operator=<>(f); // This is the non-debug one
g.operator=<true>(f); // This is the non-debug one
g.operator=<false>(f); // This is the debug one

您当然仍然可以写g = f

不幸的是,尽管您在编写本文时无法编写g=<false>f;,所以设想的调用语法很丑陋。

答案 3 :(得分:0)

注意:仅当复制构造函数完全执行复制赋值运算符应该执行的操作(递增静态计数器除外)时,这才有效。

Foo operator=(const Foo& b) 
{
    ++counter;

    //Somehow call default functionality of = opreator for foo.
    Foo copy(b);
    return copy;

    //counter++;
}

您可以在onlinegdb上查看我的代码。

除了上面提到的那个以外,我不确定使用此方法有其他陷阱。批评是最欢迎的。