我想用重载包装操作符函数以用于调试。
例如:我想计算在为Foo对象运行程序期间完成了多少次操作。
static int counter = 0;
Foo operator=(const Foo& b)
{
//Somehow call default functionality of = opreator for foo.
counter++;
}
在重载运算符时是否可以仅调用运算符的默认功能。就像编写覆盖函数时调用覆盖函数的基本函数一样。
答案 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上查看我的代码。
除了上面提到的那个以外,我不确定使用此方法有其他陷阱。批评是最欢迎的。