我是C ++的新手,并努力尝试使多文件程序工作。我有一个用C语言运行的Graph库,我遇到了将它转换为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â”,我认为这一切都来自于我如何声明。我在这里环顾四周,发现其他人抱怨这个错误,但我没有看到它有助于分配一个数组。帮助会很棒,因为除此之外我知道一切都有效。
答案 0 :(得分:2)
您已将Graph::adj
声明为List*
类型(adj[i]
与执行*(adj+i)
相同),并取消引用指向T
类型的指针产生类型T
的值,即。 adj[i]
的类型为List
。
如果你真的想要做你想做的事情,将Graph::adj
声明为List**
,那么它将指向一堆指向List
的指针,而不是指针到了一堆List
s。
我不明白,你想说什么?
您正尝试将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
答案 1 :(得分:1)
行
adj = static_cast<List*>(calloc(n + 1, sizeof(List*)));
建议 adj 是列表对象的数组,而行
adj[i] = new List();
表明它是一个指针数组。您应该检查 adj 的定义。顺便说一下,错误是指后一行。
<强>类型强>
我将详细阐述问题的理论方面,围绕C ++类型系统。
在C ++中,每个表达式都有一个 type ,在编译时已知。 表单的任何表达式的类型
static_cast<List*>(...)
是
List *
也就是说,如果括号中的表达式的类型可以静态地转换为List *,则编译器不会抱怨并且表达式的最终类型将是List *。函数 calloc 返回void *,可以将其转换为任何其他指针;实际上,指针强制转换通常只是告诉编译器的一种方式是的,我知道我在做什么,闭嘴。在大多数平台上,所有指针类型都具有相同的位表示,尽管标准不强制要求这样做,因此原则上不需要生成机器代码来实现这样的转换。
表达式的类型,例如
new List()
或
new List[10]
是
List *
并且包含此类指令的指令为 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
好消息是,如果您使用新运算符分配 adj ,则可能不需要每次都使用 new 进行创建单一元素;当您使用 new 分配数组时,会创建其所有元素,并且编译器会自动调用它们的构造函数。
可能的解决方案
由于你的程序的其余部分非常正确,你可以简单地删除
行adj[i] = new List()
一切都应该正常。然而,正如 john 所指出的那样,你的意图并不是很清楚;你真的需要告诉我们你是否希望 adj 成为一个对象数组
List *adj;
或指针数组
List **adj;
高级主题
使用C方式之间的实际区别
adj = static_cast<List*>(calloc(n + 1, sizeof(List*)));
或C ++方式
adj = new List[n + 1];
是否使用前一种方法调用每个已分配的 List 对象的构造函数。有一些指针的应用程序你可能希望这样,但一般情况下你不应该混合使用C和C ++。
答案 2 :(得分:0)
C和C ++的混合组合实际上比纯C ++更难。
在这种情况下,问题似乎是你有
class Graph
{
...
List* adj;
...
};
所以
adj[i] = new List();
是错误的,因为adj[i]
的类型为List
而new List()
的类型为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)));