实例化一个二维数组并在C ++

时间:2016-07-13 02:36:41

标签: c++ class constructor

我非常了解C(10年),但我是C ++新手。我得到以下的错误:

hw2.cpp: In function ‘int main()’:
hw2.cpp:337:7: error: no match for ‘operator=’ (operand types are     ‘Graph’ and ‘Graph*’)
grph = new Graph(size);
   ^
hw2.cpp:337:7: note: candidate is:
hw2.cpp:17:7: note: Graph& Graph::operator=(const Graph&)
class Graph {
   ^
hw2.cpp:17:7: note:   no known conversion for argument 1 from ‘Graph*’   to ‘const Graph&’

我的类和构造函数是:

class Graph {
//
//  Class Graph --  contains the graph x, y of size Size showing          connectivity
 //                 (whether node X is connected to node Y) and the cost of
 //                 the connection between X and Y.
//
private:
int nNodes;
vector<vector<int>> gph;
public:
//
//  Constructors
//

explicit Graph(int size=50):nNodes(size){

    gph = new int *[size];
    for (int i = 0; i < size;i++)
        gph[i] = new int[size];
}
//
//  Destructors
//
~Graph(void){
    retgph();
}
//
//  Methods
//
void retgph(){

 }
 int getLength(
    int x,      // Node x
    int y){     // Node y
    return (gph[x][y]);
}
void setGraph(
    int nodeX,  // Node X
    int nodeY,  // Node Y
    int value   // Value to set it to.
    ){
gph[nodeX][nodeY]=value;
gph[nodeY][nodeX]=value;
return;
}

};

我的主要代码是:

int main(){
Graph abc;  // graph object.
Open  opn;  // open set object.
int final;  // final node which should be destination.
const int size = 10;
const int source=0; // source node.
const int dest=5;   // destination node.
abc = new Graph(size);
opn  = new Open(size);

请不要跟我说话,因为我不知道自己在做什么。我认为     ABC =新图(50) 应该实例化一个对象ABC,但图形是在构造函数Graph(int = size)中构建的,并且是GPH。当我说ABC.setNodeValue(1,2,3)时我访问了什么图表; ?类中的图GPH或另一个ABC实例化?如果它是一个实例化的(ABC)为什么GPH出现在Graph类中呢?我的想法是ABC是由方法操纵的(ABC.getNodeValue(47);)。类中的GPH是否只是作为实例化过程的模型出现在那里? GPH实际上也是INT ** GPH; 。您将给予我的任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:2)

当你最初说Graph abc;时,你正在堆栈上构建一个Graph对象(使用它的默认构造函数,在这种情况下是一个默认的转换构造函数,给出图形的大小50)。

然后尝试将类型Graph *的内容分配给此变量,因为这是new返回的内容(指向堆上新构造的对象的指针),这显然不是与变量的类型相同。这就是为什么编译器抱怨这些类型之间缺少operator=(赋值运算符)的原因,并建议你打算使用复制赋值运算符,因为它与你的&#39;非常匹配。重新尝试,但仍然不正确。也许你正在尝试做以下事情:

const int size = 10;

Graph abc(size);
Open  opn(size);

或许如果你确实需要通过指针存储它们:

const int size = 10;

Graph *abc = new Graph(size);
Open  *opn = new Open(size);

// Do stuff...

delete opn;
delete abc;

答案 1 :(得分:0)

Graph课程中,gph成员是包含std::vector元素的std::vectorstd::vectornew[]delete[]的包装器,因此无需直接使用它们来分配矢量。要在运行时更改std::vector的大小,您可以使用其resize()方法,例如:

class Graph {
private:
    vector< vector<int> > gph;
public:
    explicit Graph(int size=50) {
        gph.resize(size);
        for (int i = 0; i < size; ++i)
            gph[i].resize(size);
    }

    /* You can even reduce the constructor even more,
    using the constructor initialization list, if you
    don't mind a little extra overhead temporarily...

    explicit Graph(int size=50)
        : gph(size, std::vector<int>(size) ) {
    }
    */

    /* not necessary to clear the vector during destruction,
    it is handled automatic by the vector's own destructor...

    ~Graph() {
        retgph();
    }
    */

    void retgph() {
        gph.clear();
    }

    int getLength(int x, int y) {
        return gph[x][y];
    }

    void setGraph(int x, int y, int value) {
        gph[x][y] = value;
    }
};

关于代码的其余部分......

new运算符返回指向堆上分配的新实例化对象的指针。因此new Graph分配一个Graph对象,在其上调用Graph()构造函数,并返回指向该对象的Graph*指针。

您的编译器错误是因为您的abc变量在堆栈上被声明为Graph实例化对象而不是Graph*指针。因此,当您调用abc = ...时,实际上是在调用Graph::operator=() 复制赋值运算符(在这种情况下,编译器会为您自动生成)。该运算符期望const Graph&(对常量Graph对象的引用)作为输入,而不是Graph*(指向Graph对象的指针),因此“没有已知的转换Graph*const Graph&“编译错误。

opn变量的相同内容,使用Open类。

abcopn变量更改为指针,并在访问这些对象的方法时将任何.更改为->。当你完成使用它们时,不要忘记delete对象:

int main() {
    const int size = 10;
    Graph *abc;  // pointer to graph object.
    Open  *opn;  // pointer to open set object.
    abc = new Graph(size);
    opn  = new Open(size);
    //...
    abc->setGraph(x, y, value);
    opn->doSomething(parameters);
    //...
    delete opn;
    delete abc;
}

或者,使用std::auto_ptrstd::unique_ptr为您处理delete

#include <memory>

int main() {
    const int size = 10;
    std::uninque_ptr<Graph> abc( new Graph(size) );
    std::unique_ptr<Graph> opn( new Open(size) )
    //...
    abc->setGraph(x, y, value);
    opn->doSomething(parameters);
    //...
}

或者,只是继续在堆栈上实例化它们,但摆脱newdelete,当main()退出时,让它们在超出范围时自毁:

int main() {
    const int size = 10;
    Graph abc(size);
    Open opn(size);
    //...
    abc.setGraph(x, y, value);
    opn.doSomething(parameters);
    //...
}

现在,回答你的问题:

  

我认为ABC = NEW GRAPH(50)应该实例化一个对象ABC,但图形是在构造函数Graph(int = size)中构建的,并且是GPH。

abc = new Graph(50)实例化一个构造函数值为50的新Graph对象,然后将该对象指针指定给abc。在内部,Graph构造函数使用指定的gph实例化size向量。

  

当我说ABC.setNodeValue(1,2,3)时,我访问了什么图表; ?类中的图GPH或另一个ABC实例化了吗?

您正在访问abc对象,该对象在内部访问gph向量。

  

如果是实例化的(ABC),为什么GPH会出现在Graph类中呢?

它是abc对象内部的一段数据。将Graph视为信封,将gph视为信封内的信息,将abc视为握住信封的信号。每次调用new Graph时,都会创建一个新的信封,其中包含一个新的gph

  

我的想法是ABC是由方法操纵的(ABC.getNodeValue(47);)。

  

类中的GPH是否只是作为实例化过程的模型出现在那里?

没有。这是被实例化的事情之一。

  

GPH实际上也是INT ** GPH;`

不在您展示的代码中。但逻辑上,这相当于2维std::vector在运行时的行为 - 指针(在外部向量内)指向动态数组(外部向量管理的)指针(内部向量)到整数的动态数组(内部向量管理的内容)(内部向量包含的内容)。

上述代码的C等价物如下所示:

struct Graph {
    int size;
    int **gph;
};

struct Open {
    //...
};

Graph* createGraph(int size=50) {
    Graph *g = (Graph*) malloc(sizeof(Graph));
    g->size = size;
    g->gph = (int**) malloc(sizeof(int**) * size);
    for (int i = 0; i < size; ++i)
        gph[i] = (int*) malloc(sizeof(int) * size);
    return g;
}

Open* createOpen(int size=50) {
    Open *o = (Open*) malloc(sizeof(Open));
    //...
    return o;
}

void retGraph(Graph *g) {
    for (int i = 0; i < g->size; ++i)
        free(gph[i]);
    free(g->gph);
    g->gph = NULL;
    g->size = 0;
}

void freeGraph(Graph* g) {
    retGraph(g);
    free(g);
}

void freeOpen(Open* o) {
    //...
    free(o);
}

int getLength(Graph *g, int x, int y) {
    return g->gph[x][y];
}

void setGraph(Graph *g, int x, int y, int value) {
    g->gph[x][y] = value;
}

void doSomething(Open *o, parameters) {
    //...
}

int main() {
    const int size = 10;
    Graph *abc = createGraph(size);
    Graph opn = createOpen(size)
    //...
    setGraph(abc, x, y, value);
    doSomething(opn, parameters);
    //...
    freeOpen(opn);
    freeGraph(abc);
}