清除c++构造函数中重复的代码

clean repeated code in C++ constructors

本文关键字:代码 c++ 构造函数 清除      更新时间:2023-10-16

我有一个c++头文件,为用户提供了几个构造函数(这是一个要求):

#ifndef IMANDEL_H_
#define IMANDEL_H_
class IMandel{
public:
    IMandel();
    IMandel(int aWidth, int aLength);
    IMandel(int threads, int aWidth, int aLength);
    //other stuff!
private:
    int max_iterations, thread_count, height, width;
    int* buffer; 
};
#endif

因此,在相应的cpp文件中,我分别实现了这些构造函数:

//default constructor
IMandel::IMandel(){
    height = 10000;
    width = 10000;
    //this code segements gets repeated in every constructor! Messy!
    max_iterations = 255;
    thread_count = 1;
    buffer = new int[width*height];
}
IMandel::IMandel(int aWidth, int aLength){
    width = aWidth;
    height = aLength;
     //this code segements gets repeated in every constructor! Messy!
    max_iterations = 255;
    thread_count = 1;
    buffer = new int[width*height];
}
IMandel::IMandel(int threads, int aWidth, int aLength){
    thread_count = threads;
    width = aWidth;
    height = aLength;
     //this code segements gets repeated in every constructor! Messy!
    max_iterations = 255;
    buffer = new int[width*height];
}

正如您所看到的,我的构造函数是不健康的,它们到处都是重复的代码块,这太可怕了!

在java中,我通过使用构造函数相互调用找到了这个问题的解决方案。基本上,我像下面这样重用构造函数(Java示例):

public myClass(){
    this(1, 10000, 10000);
}
public myClass(int aWidth, int aLength){
   this(1, aWidth, aLentgh);
}
public myClass(int threads, int aWidth, int aLength){
   thread_count = threads;
   width = aWidth;
   height = aLength;
   max_iterations = 255;
   buffer = new int[width*height];
}

正如您在这个Java示例中看到的,不同的构造函数之间没有重复的代码。问题:

  1. 有没有办法在c++中实现同样的效果?
  2. 如果是,如何?你能提供样品吗?
  3. 如果没有,您建议如何解决这个问题?

实际的解决方案各不相同,这取决于您使用的是哪个版本的c++。

在c++ 03中,一种常见的(但不完美-参见底部有用的注释)方法是创建一个所有构造函数调用的init()函数。所有三个构造函数都可以是一行,这样调用函数:

void IMandel::init(int threads, int aWidth, int aLength){
    thread_count = threads;
    width = aWidth;
    height = aLength;
     //this code segements gets repeated in every constructor! Messy!
    max_iterations = 255;
    buffer = new int[width*height];
}
//default constructor
IMandel::IMandel(){
    init( 1, 10000, 10000 );
}
IMandel::IMandel(int aWidth, int aLength){
    init( 1, aWidth, aLength );
}
IMandel::IMandel(int threads, int aWidth, int aLength){
    init( threads, aWidth, aLength );
}

在c++ 11中,允许构造函数调用其他构造函数,就像@chris注释的那样。你可以这样修改你的构造函数:

//default constructor
IMandel::IMandel()
: IMandel( 1, 10000, 10000 )
{
}
IMandel::IMandel(int aWidth, int aLength)
: IMandel( 1, aWidth, aLength )
{
}
IMandel::IMandel(int threads, int aWidth, int aLength){
    thread_count = threads;
    width = aWidth;
    height = aLength;
     //this code segements gets repeated in every constructor! Messy!
    max_iterations = 255;
    buffer = new int[width*height];
}

采用哪种解决方案取决于具体情况。

这是你当前的类定义:

class IMandel
{
public:
    IMandel();
    IMandel(int aWidth, int aLength);
    IMandel(int threads, int aWidth, int aLength);
    //other stuff!
private:
    int max_iterations, thread_count, height, width;
    int* buffer; 
};

我是这样定义它的:

class IMandel
{
public:
    IMandel( int aWidth = 10000, int aLength = 10000, int threads = 1 );
    //other stuff!
private:
    int max_iterations, thread_count, height, width;
    std::vector<int> buffer;
};

注意,除了参数顺序之外,这仍然给了你原来的明显的构造函数。

没有必要把事情弄得过于复杂,也就是说,KEEP IT SIMPLE。然而,c++ 03的其他方法包括一个通用的init函数(如果适用的话,不在这里)和一个通用的人工基类。其他c++ 11方法包括构造函数转发。


顺便说一下,请注意你的原始代码违反了"三规则",即它需要禁止或显式支持复制,但没有做到这一点。上面给出的简化不会受到这个问题的影响。你知道为什么吗?

如果你的编译器支持c++ 11的委托构造函数,可以减少构造函数中重复的代码。在你的情况下,似乎你只需要为你的构造函数参数提供默认值。

#ifndef IMANDEL_H_
#define IMANDEL_H_
class IMandel{
public:
    IMandel(int aWidth = 10000, int aLength = 10000, int threads = 1);
private:
    int max_iterations, thread_count, height, width;
    int* buffer; 
};
#endif
IMandel::IMandel(int aWidth, int aLength, int threads)
: max_iterations(255)
, thread_count(threads)
, height(aLength)
, width(aWidth)
, buffer(new int[width*height])
{
}

上面的构造函数完成了您所展示的3所做的一切。另外,考虑为buffer使用vector<int>,而不是自己管理内存。