什么叫“间接寻址级别不同”,这错误什么意思。麻烦老大们帮忙解释下。

unhappyless_23 2007-09-03 11:45:02
用强制类型转换可以解决,但我想知道这是为什么错,第一次见到这错误

#include <iostream>
using namespace std;

class test
{
public:
test(int* pi)
{
this->pi=pi;
}
private:
int* pi;

};

int main()
{
int *p = new int (8);
test(p);
}

c:\documents and settings\wengtn\my documents\visual studio 2005\projects\werwer\werwer\weeeeer.cpp(60) : error C2040: “p”: “test”与“int *”的间接寻址级别不同
c:\documents and settings\wengtn\my documents\visual studio 2005\projects\werwer\werwer\weeeeer.cpp(60) : error C2512: “test”: 没有合适的默认构造函数可用
...全文
9776 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
denglongmakeit 2011-11-02
  • 打赏
  • 举报
回复 1
我在用数组时也遇到了这个错误
边城狂人 2007-09-08
  • 打赏
  • 举报
回复
变量名就是一个标识符,标识符是由字母或下划线开头的字母数据下载线的组合。
(int*) p显示不符合标记符的规则嘛。
unhappyless_23 2007-09-07
  • 打赏
  • 举报
回复
To: jamesfancy(边城狂人)

(int*) p 会被编译器认为是一个数据,变量名是绝不可能是这个样子的,所以就用这个数据作为参数构造test对象了,所以强制转换之后不会出错。

为什么 “变量名是绝不可能是这个样子的”?
unhappyless_23 2007-09-06
  • 打赏
  • 举报
回复
(int*) p 会被编译器认为是一个数据,变量名是绝不可能是这个样子的,所以就用这个数据作为参数构造test对象了,所以强制转换之后不会出错。

为什么 “变量名是绝不可能是这个样子的”?
边城狂人 2007-09-05
  • 打赏
  • 举报
回复
red_berries(我再顶顶) ( ) 信誉:100 2007-09-04 23:05:39 得分: 0

LS我好像在JSP区见过你啊,两个星星,嘿嘿,
你怎么也搞C++啊,我现在正矛盾是搞C++还是JSP呢,能否谈谈见解?
___________________________________

我在学Java之前就会C++了。学Java是因为找到的那份工作要用Java。
现在你两个都可以学,找到工作了之后用啥你就主攻啥。

kuike 2007-09-05
  • 打赏
  • 举报
回复
c++声明(declare)一个局部变量后,这个局部变量就会被自动定义了(define),也就是分配了相应的存储空间,并且调用相应的构造函数(如果有的话)。所以test(p)不只是声明,而且也实例化了,也调用构造函数。详细可以看看这里的反汇编代码。
lddLinan 2007-09-05
  • 打赏
  • 举报
回复
相关标准:
6.8 Ambiguity resolution [stmt.ambig]
1 There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with
a function-style explicit type conversion (5.2.3) as its leftmost subexpression can be indistinguishable from a declaration
where the first declarator starts with a (. In those cases the statement is a declaration. [ Note: To disambiguate, the whole
statement might have to be examined to determine if it is an expression-statement or a declaration. This disambiguates
many examples. [ Example: assuming T is a simple-type-specifier (7.1.5),
T(a)->m = 7; / / expression-statement
T(a )++; / / expression-statement
T(a ,5)<<c; / / expression-statement
T(*d)( int ); / / declaration
T(e )[5]; / / declaration
T(f ) = { 1 , 2 }; / / declaration
T(*g)( double (3)); / / declaration
In the last example above, g, which is a pointer to T, is initialized to double(3). This is of course ill-formed for
semantic reasons, but that does not affect the syntactic analysis. —end example ]

一言以蔽之,能作为声明的语句就被认作是声明, 所以这里test(p)背认定为声明而不是构造一个临时的test变量。

“test(p)语句试图把生成的test实例转换为int*类型,”这里不存在“实例类型转换“的问题,int*类型的实例是可以转换为test实例的,可能vc6.0在声明和定义之间做出错误或是过晚的抉择造成的。
kuike 2007-09-05
  • 打赏
  • 举报
回复
修正前面个错误,应该是[test((int*)p)将会通过编译,]
kuike 2007-09-05
  • 打赏
  • 举报
回复
gfxiang(afu)和jamesfancy(边城狂人) 正解

补充解释一下这两个错:
error C2040: “p”: “test”与“int *”的间接寻址级别不同
error C2512: “test”: 没有合适的默认构造函数可用

单纯的语句 test(p); 将定义一个test类实例p,相当于 test p; 但test并没有定义默认构造函数,所以有了第二个错。另因为p以声明为int*类型,而test(p)语句试图把生成的test实例转换为int*类型,这就引发了第一个错,因为一个test实例和一个指针有着不同的寻址级(different levels of indirection)。
test((int* p))将会通过编译,是因为这里(int* p)被解析为构造函数的参数,而非新test实例的名称。这句语句在运行时将生成一个无名test实例,其pi被初始化为p;因为无名,该实例不可访问,所以纯粹无用。
这里g++和vs2005两个编译器报不同的错误是似乎是因为两者解析的顺序的不同。在vs2005里修正了第一个错误后,以如下语句编译,将会得到和g++同样的报错。
int p=9;
test(p);//error C2371: 'p' : redefinition; different basic types
unhappyless_23 2007-09-04
  • 打赏
  • 举报
回复
哦,那我为什么用强制类型转换能解决?
p 本来就是 int*
为什么(int *)p 后就可以,不是多余了吗?强制类型转换是不是还有其他什么用途?
red_berries 2007-09-04
  • 打赏
  • 举报
回复
LS我好像在JSP区见过你啊,两个星星,嘿嘿,
你怎么也搞C++啊,我现在正矛盾是搞C++还是JSP呢,能否谈谈见解?
边城狂人 2007-09-04
  • 打赏
  • 举报
回复
gfxiang(afu) 说对了

test(x)和test x是等价的,都是申明变量。
原来()可以用在申明中把变量名包起来,通常申明函数指针的时候会用到,原来用于一般变量也可以这样。

(int*) p 会被编译器认为是一个数据,变量名是绝不可能是这个样子的,所以就用这个数据作为参数构造test对象了,所以强制转换之后不会出错。

C++太神奇了,呵呵!
边城狂人 2007-09-04
  • 打赏
  • 举报
回复
看样子编译器是把test(p)当成是一个函数调用了。不过奇怪的是什么把p加了强制类型申明之后就对了呢?我糊涂了!!

我试了一下,如果再定义一个void test(int* p)的函数,编译就不会报错了。

在没有void test(int*)函数的时候,test((int*) p)会调用构造函数,在构造里加一条输出语句就知道了。
但是定义了void test(int*)之后,test(p)和test((int*) p)都会去调用函数——这到是说得过去

唯一不明白的是,为什么没有(int*)的时候编译不过,有了就没问题了。
unhappyless_23 2007-09-04
  • 打赏
  • 举报
回复
哦,那我为什么用强制类型转换能解决?
p 本来就是 int*
为什么(int *)p 后就可以,不是多余了吗?强制类型转换是不是还有其他什么用途?
gfxiang 2007-09-04
  • 打赏
  • 举报
回复
test.cpp: In function `int main()':
test.cpp:19: error: conflicting declaration 'test p'
test.cpp:18: error: 'p' has a previous declaration as `int*p'
test.cpp:19: error: declaration of `test p'
test.cpp:18: error: conflicts with previous declaration `int*p'
test.cpp:19: error: no matching function for call to `test::test()'
test.cpp:5: note: candidates are: test::test(const test&)
test.cpp:8: note: test::test(int*)

上面代码用g++编译报上面的错误,g++编译器认为test(p);等价于 test p;当着变量定义了,和前面的定义冲突了。
边城狂人 2007-09-03
  • 打赏
  • 举报
回复
编译器以为你的test(p)是调用的一个函数,而test实际是一个类。所以报错。
如果你改成 test a(p)就不会有问题了。

64,660

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧