0

我是 C++ 新手,正在努力尝试使多文件程序正常工作。我有一个用 C 语言运行的图形库,但在将其转换为 C++ 时遇到了麻烦。g++ 我最大的问题是这个错误信息,

error: no match for âoperator=â in â*(((Graph*)this)->Graph::adj +
((long unsigned int)(((long unsigned int)i) * 32ul))) = (operator
new(32u), (<statement>, ((List*)<anonymous>)))â

这是我抱怨的 Graph.cpp 代码部分:

Graph::Graph(int n){
    order = n;
    size = 0;
    source = NIL;
    color = static_cast<char*>(calloc(n + 1, sizeof(char)));
    distance = static_cast<int*>(calloc(n + 1, sizeof(int)));
    parent = static_cast<int*>(calloc(n + 1, sizeof(int)));
    adj = static_cast<List*>(calloc(n + 1, sizeof(List*)));
    discover = static_cast<int*>(calloc(n + 1, sizeof(int)));
    finish = static_cast<int*>(calloc(n + 1, sizeof(int)));
    int i;
    for(i = 0; i <= n; i++){
        color[i] = 'w';
        distance[i] = INF;
        parent[i] = NIL;
        adj[i] = new List();
    }
}

正如您所看到的,我在 C 和 C++ 之间使用了一些混合体,但是纯 C++ 实现也不起作用。在我的文件中,我不断收到错误“错误:â->â 的基本操作数具有非指针类型âListâ”,我认为这一切都来自我的声明方式。我在这里环顾四周,发现其他人抱怨这个错误,但我没有看到它有助于分配给数组。帮助会很棒,因为除此之外我知道这一切都有效。

4

3 回答 3

2

您已声明Graph::adj为 type List*adj[i]与做相同*(adj+i)),并且取消引用指向 type 的指针T将产生 type 的值T,即。的类型adj[i]List

如果你真的想做你想做的声明Graph::adjas List**,那么它将是一个指向一堆指针的指针List,而不是一个指向一堆Lists 的指针。


我不明白,你到底想说什么?

您正在尝试将 a List*(由 返回new List)分配给 类型的变量List

struct List {
  // ... 
};

List ** adj = static_cast<List**> (
  std::calloc (10, sizeof (List*))
);

/* error

   List * adj = static_cast<List*> (
     std::calloc (10, sizeof (List*))
   );

*/

adj[0] = new List;

好的,我明白了.. 但是必须有更好的方法来解决这个问题?

可以肯定的是,使用 c++ 为您提供的东西并抛弃您的旧 C 习惯。

List * adj = new List [10]; // create an array of 10 List

adj[i].member_of_List ...;  // example

delete [] adj;              // free up allocated memory when you are done
于 2013-04-23T05:45:30.373 回答
1

线

adj = static_cast<List*>(calloc(n + 1, sizeof(List*)));

表明adjList对象的数组,而 line

adj[i] = new List();

表明它是一个指针数组。您应该检查adj的定义。顺便说一句,错误是指后一行。

类型

我将详细阐述这个问题的理论方面,它围绕 C++ 类型系统展开。

在 C++ 中,每个表达式都有一个类型,在编译时就知道了。表单的任何表达式的类型

static_cast<List*>(...)

List *

也就是说,只要括号中的表达式类型可以静态转换为 List *,编译器就不会报错,表达式的最终类型将是 List *。函数calloc返回 void * 可以转换为任何其他指针;事实上,指针转换通常只是告诉编译器是的,我知道我在做什么,闭嘴的一种方式。在大多数平台上,所有指针类型都具有相同的位表示,尽管标准没有强制要求这样的事情,因此原则上不需要生成机器代码来实现这种转换。

表达式的类型,例如

new List()

或者

new List[10]

List *

并且包含此类指令的指令会为一个列表对象或 10 个列表对象分配足够的空间,并返回一个指向该空间的指针。

如果您更换线路,您可能会更好

adj = static_cast<List*>(calloc(n + 1, sizeof(List*)));

adj = new List[n + 1];

如果adj是指针类型,则表达式的类型如

adj[i]

或者

*(adj + i)

甚至简单地

*adj

是指针类型减去一个星号;也就是说,如果adj的类型是

List *

adj[i]的类型是

List

这就是您在adj[i] = new List()行处收到错误的原因;分配没有意义

List *

List

好消息是,如果您使用new运算符分配adj,您可能不需要使用new来创建每个元素;当你用new分配一个数组时,它的所有元素都会被创建,并且编译器会自动调用它们的构造函数。

可能的解决方案

由于您的程序的其余部分显然是正确的,您可以简单地擦除该行

adj[i] = new List()

一切都应该正常。但是,正如约翰指出的那样,您的意图不是很清楚。你真的需要告诉我们你是否想让adj成为一个对象数组

List *adj;

或指针数组

List **adj;

进阶话题

使用C方式的实际区别

adj = static_cast<List*>(calloc(n + 1, sizeof(List*)));

或 C++ 方式

adj = new List[n + 1];

是不是每个分配的List对象的构造函数都不会被前一种方法调用。您可能希望在一些指针应用程序中出现这种情况,但通常您不应该混合使用 C 和 C++。

于 2013-04-23T05:46:13.173 回答
0

C 和 C++ 的混合混合实际上比纯 C++ 更难。

在这种情况下,问题似乎是你有

class Graph
{
    ...
    List* adj;
    ...
};

所以

adj[i] = new List();

是错误的,因为adj[i]is of typeList并且new List()is of type List*

解决此问题的方法是使用Placement new

#include <new>

new (adj + i) List();

这将构建一个List地址&adj[i],我认为这是您想要实现的。

但这是高级 C++ 并且只有在您尝试编写 C 和 C++ 的混合时才有必要。我会尽快放弃 C 部分。

编辑

好的,正如 refp 指出的那样(我错过了)你有

adj = static_cast<List*>(calloc(n + 1, sizeof(List*)));

只有当这是一个错误并且您打算这样做时,我的回答才是正确的

adj = static_cast<List*>(calloc(n + 1, sizeof(List)));
于 2013-04-23T05:58:01.093 回答