C++ 用于类构造函数、析构函数和运算符重载的实用函数

C++ 用于类构造函数、析构函数和运算符重载的实用函数,c++,constructor,operator-overloading,destructor,C++,Constructor,Operator Overloading,Destructor,不久前,我在一个网站上发现了一些实用函数的代码示例,这些函数在创建、销毁对象时使用,甚至在重载一些操作符时使用。 更准确地说,主要使用以下成员函数:init、copy、set和destroy initmember函数用于初始化所有私有成员。它主要在构造函数中调用,例如默认或参数构造函数 copy成员函数用于对作为常量引用传递的对象进行深度复制。它在引用构造函数和操作符的重载中调用 set成员函数,主要为需要它的私有成员分配内存 最后,destroy成员函数用于释放分配的内存。例如,它在析构函数

不久前,我在一个网站上发现了一些实用函数的代码示例,这些函数在
创建
销毁
对象时使用,甚至在重载一些
操作符时使用。
更准确地说,主要使用以下成员函数:init、copy、set和destroy

  • init
    member函数用于初始化所有私有成员。它主要在
    构造函数
    中调用,例如
    默认
    参数构造函数
  • copy
    成员函数用于对作为
    常量引用传递的对象进行
    深度复制
    。它在
    引用构造函数
    操作符的重载中调用
    
  • set
    成员函数,主要为需要它的
    私有成员分配
    内存
    
  • 最后,
    destroy
    成员函数用于
    释放分配的内存。例如,它在
    析构函数的内部被调用
我想听听你的意见,知道这是否是一个好的编程实践?优点和缺点是什么?欢迎任何意见和建议! 下面,我将说明如何为
CMatrix
类定义这些成员函数

矩阵h
模板
类CMatrix{
CMatrix(){this->initMatrix();}
CMatrix(整数nRows、整数nCols、整数nChannels){
这->initComplexMatrix();
此->setComplexMatrix(nRows、nCols、nChannels);
}
CMatrix(常数CMatrix和参考矩阵){
这->initComplexMatrix();
此->copyComplexMatrix(参考矩阵);
}
CMatrix和运算符=(常数CMatrix和参考矩阵){
如果(此!=&refMatrix){
这->销毁复杂矩阵();
这->initComplexMatrix();
此->copyComplexMatrix(参考矩阵);
}
返回(*本条);
}
T&CMatrix::operator()(int,int,int);
CMatrix::operator()(int,int,int)const;
......
void initMatrix();
无效复制矩阵(常数CMatrix&);
void集合矩阵(int,int,int=1);
无效矩阵();
......
~CMatrix(){this->destroyMatrix();}
私人:
数据;
国际货币基金组织;
国际货币基金组织;
内部通道;
};
matrix.cpp
#包括
模板
内联T&CMatrix::operator()(int-mrow、int-mcol、int-mchannel){
断言(mrow>=0&&mrowgetRows());
断言(mcol>=0&&mcolgetCols());
断言(mchannel>=0&&mchannelgetChannels());
返回此->m_pData[mrow][mcol][mcchannel];
}
模板
void CMatrix::initMatrix(){
此->m_nRows=0;
这个->m_nCols=0;
这->m_nChannels=0;
此->m_pData=NULL;
}
模板
void CMatrix::copyMatrix(常数CMatrix和参考矩阵){
if(refMatrix.m_pData!=NULL){
这->设置矩阵(refMatrix.getRows(),refMatrix.getCols(),refMatrix.getChannels());
对于(寄存器int dy=0;dygetRows();dy++){
对于(寄存器int dx=0;dxgetCols();dx++){
对于(寄存器int ch=0;chgetChannels();ch++){
这->m_pData[(dy)][(dx)][(ch)]=refMatrix.m_pData[(dy)][(dx)][(ch)];
}
}
}
}
否则{
此->m_pData=NULL;
}
}
模板
void CMatrix::setMatrix(int nRows、int nCols、int nChannels){
这个->破坏矩阵();
此->m_pData=NULL;
这->m_pData=newt**[nRows];
用于(寄存器int dy=0;dym_pData[dy]=NULL;
这->m_pData[dy]=新的T*[nCols];
用于(寄存器int dx=0;dxm_pData[dy][dx]=NULL;
这->m_pData[dy][dx]=新的T[nChannels];
}
}
这->设置行(mrows);
此->设置COLS(mcols);
此->设置通道(多通道);
}
模板
void CMatrix::destroyMatrix(){
如果(此->m_pData!=NULL){
对于(寄存器int dy=0;dygetRows();dy++){
对于(寄存器int dx=0;dxgetCols();dx++){
删除[]此->m_pData[dy][dx];
}
删除[]此->m_pData[dy];
}
删除[]此->m_pData;
此->m_pData=NULL;
} 
}

不,不建议这样做。您提出的方法不是异常安全的,并且与需要非默认构造的
const
或子对象不兼容

而是使用ctor初始值设定项列表。代码重用可以通过在ctor初始值设定项列表中调用静态帮助函数或将逻辑移动到子对象构造函数中来实现

对于内存分配,每个资源使用一个子对象。内存管理逻辑在子对象构造函数和析构函数中结束。在许多情况下,您可以使用库中现有的RAII类,例如
std::vector
,而无需自己编写任何内存管理代码

大多数操作符都可以使用

编辑:异常安全构造可能如下所示:

#include <vector>
template<typename T>
class matrix
{
    int m_nCols;
    std::vector<T*> m_rows;
    std::vector<T> m_cells;
    size_t makeIndex( int row, int col ) const { return row*m_nCols + col; }

public:    
    matrix( int nRows, int nCols )
        : m_nCols(nCols), m_rows(nRows), m_cells(nRows * nCols)
    {
        while (nRows--) m_rows[nRows] = &m_cells[nRows * nCols];
    }

    matrix( const matrix<T>& other )
        : m_nCols(other.m_nCols), m_rows(other.m_rows.size()), m_cells(other.m_cells)
    {
        int nRows = other.m_rows.size();
        while (nRows--) m_rows[nRows] = &m_cells[nRows * nCols];
    }

    void swap( matrix& other )
    {
        using std::swap;
        swap(m_nCols, other.m_nCols);
        swap(m_rows, other.m_rows);
        swap(m_cells, other.m_cells);
    }

    matrix& operator=( matrix other )
    {
        other.swap(*this);
        return *this;
    }

    const T& operator()( int row, int col ) const { return m_cells[makeIndex(row,col)]; }
    T& operator()( int row, int col ) { return m_cells[makeIndex(row,col)]; }
};

不,不建议这样做。您提出的方法不是异常安全的,并且与需要非默认构造的
const
或子对象不兼容

而是使用ctor初始值设定项列表。代码重用可以通过在ctor初始值设定项列表中调用静态帮助函数或将逻辑移动到子对象构造函数中来实现

对于内存分配,每个资源使用一个子对象。内存管理逻辑在子对象构造函数和析构函数中结束。在许多情况下,您可以使用库中现有的RAII类,例如
std::vector
,而无需自己编写任何内存管理代码

大多数操作员可以在co中重用逻辑
#include <matrix.h>

template < class T >
inline T & CMatrix<T>::operator()(int mrow, int mcol, int mchannel){

    assert(mrow >= 0 && mrow < this->getRows());
    assert(mcol >= 0 && mcol < this->getCols());
    assert(mchannel >= 0 && mchannel < this->getChannels());

    return this->m_pData[mrow][mcol][mchannel];
}

template < class T >
void CMatrix<T>::initMatrix(){
    this->m_nRows   = 0;
    this->m_nCols   = 0;
    this->m_nChannels= 0;
    this->m_pData   = NULL;
}

template < class T >
void CMatrix<T>::copyMatrix(const CMatrix<T> & refMatrix){

    if(refMatrix.m_pData!=NULL){

        this->setMatrix(refMatrix.getRows(), refMatrix.getCols(), refMatrix.getChannels());

        for(register int dy=0; dy < this->getRows(); dy++){
            for(register int dx=0; dx < this->getCols(); dx++){
                for(register int ch=0; ch < this->getChannels(); ch++){ 
                    this->m_pData[(dy)][(dx)][(ch)] = refMatrix.m_pData[(dy)][(dx)][(ch)];
                }
            }
        }
    }
    else{
        this->m_pData = NULL;
    }
}

template < class T >
void CMatrix<T>::setMatrix(int nRows, int nCols, int nChannels){

    this->destroyMatrix();

    this->m_pData = NULL;
    this->m_pData = new T ** [nRows];

    for(register int dy=0; dy < nRows; dy++){
        this->m_pData[dy] = NULL;
        this->m_pData[dy] = new T * [nCols];
        for(register int dx=0; dx < nCols; dx++){
            this->m_pData[dy][dx] = NULL;
            this->m_pData[dy][dx] = new T[nChannels];
        }
    }

    this->setRows(mrows);
    this->setCols(mcols);
    this->setChannels(mchannels);
}

template < class T >
void CMatrix<T>::destroyMatrix(){

    if(this->m_pData!=NULL){

        for(register int dy=0; dy < this->getRows(); dy++){
            for(register int dx=0; dx < this->getCols(); dx++){
                delete [] this->m_pData[dy][dx];
            }
            delete [] this->m_pData[dy];
        }

        delete [] this->m_pData;
        this->m_pData = NULL;
    } 
}
#include <vector>
template<typename T>
class matrix
{
    int m_nCols;
    std::vector<T*> m_rows;
    std::vector<T> m_cells;
    size_t makeIndex( int row, int col ) const { return row*m_nCols + col; }

public:    
    matrix( int nRows, int nCols )
        : m_nCols(nCols), m_rows(nRows), m_cells(nRows * nCols)
    {
        while (nRows--) m_rows[nRows] = &m_cells[nRows * nCols];
    }

    matrix( const matrix<T>& other )
        : m_nCols(other.m_nCols), m_rows(other.m_rows.size()), m_cells(other.m_cells)
    {
        int nRows = other.m_rows.size();
        while (nRows--) m_rows[nRows] = &m_cells[nRows * nCols];
    }

    void swap( matrix& other )
    {
        using std::swap;
        swap(m_nCols, other.m_nCols);
        swap(m_rows, other.m_rows);
        swap(m_cells, other.m_cells);
    }

    matrix& operator=( matrix other )
    {
        other.swap(*this);
        return *this;
    }

    const T& operator()( int row, int col ) const { return m_cells[makeIndex(row,col)]; }
    T& operator()( int row, int col ) { return m_cells[makeIndex(row,col)]; }
};
#include <vector>
template<typename T>
class cube
{
    int m_nCols, m_nRows;
    std::vector<T> m_cells;
    size_t makeIndex( int row, int col, int channel ) const { return (channel*m_nRows + row)*m_nCols + col; }

public:    
    cube( int nRows, int nCols, int nChannels )
        : m_nCols(nCols), m_nRows(nRows), m_cells(nRows * nCols * nChannels)
    {
    }

    cube( const cube<T>& other )
        : m_nCols(other.m_nCols), m_nRows(other.m_nRows), m_cells(other.m_cells)
    {
    }

    void swap( cube& other )
    {
        using std::swap;
        swap(m_nCols, other.m_nCols);
        swap(m_nRows, other.m_nRows);
        swap(m_cells, other.m_cells);
    }

    cube& operator=( cube other )
    {
        other.swap(*this);
        return *this;
    }

    const T& operator()( int row, int col, int channel ) const { return m_cells[makeIndex(row,col,channel)]; }
    T& operator()( int row, int col, int channel ) { return m_cells[makeIndex(row,col,channel)]; }

    class channel_iterator
    {
        cube& const cube;
        int const row, col;
        int channel;
        friend class cube;
        channel_iterator( cube& all, int r, int c, int n ) : cube(all), row(r), col(c), channel(n) {}
    public:
        T& operator*() const { return cube(row, col, channel); }
        channel_iterator& operator++() { ++channel; return *this; }
        channel_iterator operator++(int) { return channel_iterator(cube, row, col, channel++); }
        bool operator!=(const channel_iterator& other) const { assert(&cube == &other.cube); return (row == other.row && col == other.col && channel == other.channel); }
    };

    int channel_count() const { return m_cells.size() / m_nRows / m_nChannels; }
    pair<channel_iterator, channel_iterator> range(int row, int col) { return make_pair(channel_iterator(*this, row, col, 0), channel_iterator(*this, row, col, channel_count())); }
};
X& X::operator= (const X& rhv)
{
    X copy(rhv); //reuse copy constructor
    this->swap(copy); //reuse swap method - also useful for the user of the class!
    //previously held resources automatically released by the destructor of copy
} 
void CMatrix<T>::swap(CMatrix<T>& other)
{
    std::swap(m_pData, other.m_pData);
    std::swap(m_nRows, other.m_nRows);
    std::swap(m_nCols, other.m_nCols);
    std::swap(m_nChannels, other.m_nChannels);
}