简体   繁体   English

C ++中的“动态构造函数”

[英]“dynamic constructor” in c++

i am new to classes in C++ and i need to create a class "Plot" which has a method that reads in data from a file and creates a 3d grid. 我是C ++类的新手,我需要创建一个“ Plot”类,该类具有一种从文件中读取数据并创建3d网格的方法。

i understand that you can make "default" constructors with default values or you can create a special constructor with predefined values. 我了解您可以使用默认值创建“默认”构造函数,也可以使用预定义值创建特殊的构造函数。

in my "private" section, i have: 在我的“私人”部分中,我有:

int nx; // number of "x" values
int ny; // number of "y" values
int nz; // number of "z" values
double* grid; // one dimensional array which stores nx*ny*nz values
double tgrid(int ix, int iy, int iz); // function which searches grid and returns value

now, i want to create my "plot" object and then AFTER that, dynamically create the "grid" array. 现在,我想创建我的“ plot”对象,然后再动态创建“ grid”数组。 is it possible to do this? 是否有可能做到这一点? or will i need to declare the size of the array "grid" when i first create "plot"? 还是在我第一次创建“绘图”时需要声明数组“网格”的大小?

Use std::vector grid; 使用std::vector grid; as your member. 作为您的会员。 Then you can use grid.resize(nx*ny*nz) to force the size you want or use grid.push_back(value); 然后,您可以使用grid.resize(nx*ny*nz)强制设置所需大小, 使用grid.push_back(value); for each value you want to add to the array. 对于要添加到数组的每个值。

It is possible: 有可能的:

class Plot{
   int nx; // number of "x" values
   int ny; // number of "y" values
   int nz; // number of "z" values
   double* grid; // one dimensional array which stores nx*ny*nz values
   double tgrid(int ix, int iy, int iz); // function which searches grid and returns value
public:
   Plot()
   {
      grid = NULL;
   }
   ~Plot()
   {
       delete[] grid;
   }
   void init(int x, int y, int z)
   {
      delete[] grid; //make sure no memory leaks since grid might have already been allocated
      nx = x;
      ny = y;
      nz = z;
      grid = new double[nx*ny*nz];
   }
};

After the construction, just call the method init: 构建之后,只需调用方法init即可:

Plot p();
p.init(2,3,4);

EDIT: 编辑:

You should however consider Mark B's answer. 但是,您应该考虑Mark B的回答。 I would also use something from std:: rather than a dynamically allocated array. 我还将使用std::而不是动态分配的数组。 Much easier to manage. 更容易管理。

EDIT2: 编辑2:

As per Constantinius' answer, avoid init() methods when you can. 根据康斯坦丁纽斯的回答,请init()避免使用init()方法。 If you specifically need the initalization AFTER construction, use it, otherwise keep all initialization logic in the constructor. 如果您特别需要初始化AFTER构造,请使用它,否则将所有初始化逻辑保留在构造函数中。

It depends on how your Plot class should be used. 这取决于应如何使用Plot类。 If you consider it necessary to create objects of this class only with valid sizes you should not allow a default constructor. 如果您认为仅需要使用有效大小创建此类的对象,则不应允许使用默认构造函数。 You do this by defining your own constructor like that: 您可以这样定义自己的构造函数:

public:
Plot(int _nx, int _ny, int _nz) : nx(_nx), ny(_ny), nz(_nz) 
{
    // initialize your array
    grid = new double[nx*ny*nz];
}

also don't forget your destructor to clear the allocated memory: 也不要忘记您的析构函数来清除分配的内存:

~Plot() 
{
    delete[] grid;
}
class Plot {
    int nx; // number of "x" values
    int ny; // number of "y" values
    int nz; // number of "z" values
    double* grid; // one dimensional array which stores nx*ny*nz values
    double tgrid(int ix, int iy, int iz); // function which searches grid and returns value
public:
    /* default constructor */
    Plot() : nx(0), ny(0), nz(0), grid(NULL) { }
    /* rule of five copy constructor */
    Plot(const Plot& b) : nx(b.nx), ny(b.ny), nz(b.nz) {
        int max = nx*ny*nz;
        if (max) {
            grid = new double(max);
            for(int i=0; i<max; ++i)
                grid[i] = b.grid[i];
        } else
            grid = NULL;
    }
    /* rule of five move constructor */
    Plot(Plot&& b) : nx(b.nx), ny(b.ny), nz(b.nz) grid(b.grid) { b.grid = NULL; }
    /* load constructor */
    Plot(std::istream& b) : nx(0), ny(0), nz(0), grid(NULL) { Load(b); }
    /* rule of five destructor */
    ~Plot() { delete[] grid; }
    /* rule of five assignment operator */
    Plot& operator=(const Plot& b) {
        int max = b.nx*b.ny*b.nz;       
        double* t = new double[max];
        for(int i=0; i<max; ++i)
            t[i] = b.grid[i];            
        //all exceptions above this line, NOW we can alter members
        nx = b.nx;
        ny = b.ny;
        nz = b.nz;
        delete [] grid;
        grid = t;
    }
    /* rule of five move operator */
    Plot& operator=(Plot&& b) {   
        nx = b.nx;
        ny = b.ny;
        nz = b.nz;
        delete [] grid;
        grid = b.grid;
        b.grid = NULL;
    }
    /* always a good idea for rule of five objects */
    void swap(const Plot& b) {
        std::swap(nx, b.nx);
        std::swap(ny, b.ny);
        std::swap(nz, b.nz);
        std::swap(grid, b.grid);
    }

    /* your load member */
    void Load(std::istream& in) {
        //load data
        //all exceptions above this line, NOW we can alter members
        //alter members
    };
};

int main() {
     Plot x;  //default constructor allocates no memory
     Plot y(x); //allocates no memory, because x has no memory
     Plot z(std::cin); //loads from stream, allocates memory
     x = z; //x.grid is _now_ given a value besides NULL.
}

This answers your questions I think. 这回答了我的问题。 Still: use a std::vector. 仍然:使用std :: vector。

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

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