用C++越久,越是觉得C++太多陷阱,真是防不胜防。 我们看这样一段代码:
#include <stdio.h>
using namespace std;
class C
{
public:
C(int a) {
printf("%d\n", __LINE__);
}
virtual ~C() {}
};
int main(int argc, char **argv)
{
C x1(1);
return 0;
}
编译执行正常,结果是:
7
然后我们改一下,把构造函数变成无参数的:
#include <stdio.h>
using namespace std;
class C
{
public:
C() {
printf("%d\n", __LINE__);
}
virtual ~C() {}
};
int main(int argc, char **argv)
{
C x1();
return 0;
}
继续编译执行,输出居然是空了!? 实在找不到任何原因,于是gdb了一下,发现根本就没有到构造函数里面。 再仔细看了一下,想起来一般无参数的类初始化都是没有括号的,于是换了一下调用方法:
int main(int argc, char **argv)
{
C x1;
return 0;
}
结果正常了~ 这是神马坑爹的语法?!有参数的时候就要有括号?没参数的时候连个空括号都不能有? 抱怨归抱怨,我们跳出来看一下:
C x1();
这行语句根本就是一行函数声明啊。。。 试想一下,有一天一个类的构造函数从一个参数变成空参数,于是你在调用的时候只是把括号里的参数删了,而括号还留着的话。。估计够你调几个小时了。。
WeAiM on #
我***。这个,要是没见过,不会想到这个。唉,一方面是对c++越来越不熟悉了,另一方面,这个实在太dt了。
Reply
sw on #
看看这个:
int b;
C x1(C2(b));
很遗憾的告诉你,这仍然是函数声明 :D
Reply
Dante on #
还真是。。。
int b;
C x1(C(b));
Reply
一念天堂 on #
这个倒是一眼就看出来了,吃过这个亏,我也记得有大牛说过:这是语言的阴暗面之一,我们只能 live with it.
Reply
Dante on #
语义的二义性。。确实如此。。
Reply
fanhe on #
c++ primer 说过了, 类类型的声明不能这样的初始化语法的.
c++ 很多细节要注意的, 非常麻烦.
Reply
dutor on #
倒不觉得奇怪,如果之前是写Java的话就另说了。
从语法分析的角度来讲,C x1();本就可以有两种解释,只不过C++优先把它当成函数声明罢了。
Reply
Dante on #
我不用java。。
嗯,语义出现二义性了。
Reply
Fangzhen on #
C++和java不一样,
C x1()就是一个函数声明,C++中如果要使用默认构造函数(就是不带参数的构造函数)的时候不用加括号。如果要动态构造一个类的话加不加括号都一样,如:
C * px=new C();
和C *p=new C;
是一样的
Reply
DJ on #
还真遇到过,不过那时候立刻调试了,一下发现没进去就明白是当成声明了
Reply
egmkang on #
哇,居然还有这个,倒真的没碰到过............
Reply
egmkang on #
C++真是到处都是坑啊
Reply
Shiina Luce on #
……这是Java写多了吧
Reply
Dante on #
我还真不用java。。
Reply
sanitizer on #
隐约记得好像C++没参数的时候,推荐使用C(void)的吧?C()算是不规范写法。
Reply
Dante on #
C(void) 也是不行的。。你可以试试。
void也可以看作是函数形参。
Reply
dutor on #
C里面C()原型可以传参,C++里面C()等价于C(void),这里面如果写成C(void)的话,就告诉编译器这就是原型,编译器就毫不犹豫咯。
下面的“匿名”兄弟太有喜感了,哈哈哈
Reply
0 on #
你不会用就别乱说,真是笑死人了!你怎么不用C x1=new C();这种方式去初始化C++代码?那岂不是更有喜剧效果?
Reply
shade on #
这位匿名的兄台~
我觉得你更搞笑一些
希望你能分享一些有营养的内容~
Reply
0 on #
真搞笑,用其他语言的语法去要求C++
Reply
匿名 on #
C()调用的是拷贝构造函数,不是无参构造函数。不要在这种基本的问题是误导新手。
Reply
Dante on #
这位朋友,虽然你的几个评论都有点尖锐,但我开始还是不打算回复你的帖子的,但是你非要说C()居然是调用拷贝构造函数这种误导性的话,我只能出来辟谣了。
C x1;
C x2(x1);
C x3 = x1;
x3 = x2;
这几行代码,你能正确的说出都调用了什么函数吗?
Reply
Sunday on #
唉,不要和此种人一般见识,无知就算了,出来让别人笑话就是他的问题了 !
Reply
Dante on #
哈哈,多谢支持~~~~
Reply
Huarong on #
一直都用new的飘过。
Reply
niuniu on #
哈哈 还真是如此~
如果C++滴水不漏,就不会有其他语言了~
Reply
1901 on #
上帝保佑我以后不要遇到这个问题,我经常写AS的啊!
Reply
dreamersdw on #
我写C++代码时,只能每增加一行,就运行一次g++。对了,还要打开http://en.cppreference.com/w/cpp 方便查找函数名,头文件。还有当写下 template 后,只能祈求苍保佑不要出错,否则我会被淹没在上千字节的错误信息中。开发效率可想而知。
《Effective C++》、《More Effective C++》、《Exceptional C++》、《More exceptional C++》、《Effective STL》、《Imperfect C++》、《Essential C++》..... 这个书单可以很长很长。有人说十年才可以学会C++,可要真是花十年在一门语言上,你还有多少时间研究算法。研究设计。
C++ 的确开发出了很多重要的软件,但这并不足以说这门语言有多好,要知道WordPress 还是用PHP写的呢。
当我学习过 Haskell 之后,才发现C++中的精华——STL,只是在模仿函数式语言中最基础的部分,而且还没有模仿好(甚至每写一个foreach 都要写一个对应的 functor,鬼才知道那个functor 还能不能复用)
用Python, Ruby, Haskell,也许是 Java 写程序,必要时调用 C++ 的 library 或许是当下不错的选择。
用的时间越长,对这种语言越反感,只想说 I hate C++
Reply
Dante on #
确实如此,说C顶多砸到脚,C++不小心就会炸飞整条腿的比喻真是非常贴切。
我现在写自己的东西都是python,简洁优雅。
可惜公司代码只能用C++,无奈。。。
Reply
springlie on #
貌似这个问题在Effective 系列中提过。。。
Reply
t.w. on #
这个问题我也奇怪过
原来果然是和函数声明一样啊
Reply
夜弓 on #
嗯,在c++里面,一个语句如果可以是函数声明,那么它就是函数声明。
Reply
Sunday on #
应该是这么回事~C++时间越长,越觉得杯具~
Reply
johnson on #
第一个你定义析构函数但是没有定义复制构造函数和赋值操作符,所以你无论你是 C x1(5),还是 C x1(1)值,对象的值是一样的。
实验方法是
你定义一个
C x1(1)
C x2(5)
你销毁 X1,C对象也将被销毁
x2也将不复存在
第二个
C x1(),无参数默认为空初始化,输出肯定为空啊
为什么等于 7 和你 你此句代码有关printf("%d\n", __LINE__);
Reply
Dante on #
朋友,你还是再回去看看C++的书吧。
Reply
t.w. on #
这个问题我也奇怪过,看了你的才理解原因,原来果然是和函数声明一样啊~
Reply
t.w. on #
这个问题我也奇怪过,看了你的才理解原因,原来果然是和函数声明一样啊
Reply
t.w. on #
这个问题我也奇怪过,
看了你的才理解原因,
原来果然是和函数声明一样啊
Reply
xheruacles on #
Declaring a class instance using a default constructor that has parameters, you should pass the arguments to let the compiler to correctly construct the object. Declaring a class instance using a default construtor that has no parameters is the same as declaring a variable, since the compiler already knows which constructor to run for you. Overloading allows the flexibilities at the cost of attention of class users to specify the exact function to run.
Reply
Terrence on #
的确如此,有些时候人的视角和编译器的视角是不是不一致的。习惯就好~
Reply
IMS on #
如果函数声明使用了C(void){}这样呢?
Reply
cplusplusisapieceofshit on #
之前学过一点c++皮毛,然后学过java之后想再回头好好学习下c++,因为觉得c++还是很牛的,但每次看个开头就看不下去了,相比java,c++就是一坨屎一样的恶心。
Reply
lssb on #
C++是一门优秀的语言,优秀不代表完美,总会存在或多或少的不习惯。但C++能流行30多年,足以说明一切问题了, ls的那个不懂就不要在那装B ,你说的话更相一坨屎
Reply
d on #
第一次遇到这个是在面试的时候,于是面试惨败
Reply
haoaina521 on #
看完评论才知道这是函数声明,并不是有参数和无参数的区别。向楼主请教两个问题,如果问题有错,麻烦指出下:1.C c;这句语句是变量的定义?在定义的时候初始化了?2.C* pC1 = new C;和C* pC2 = new C();有什么不同?
Reply
helloworld on #
求教,为什么是函数声明?另外,这句代码的原义是以b为参数构造一个C的对象,然后调用拷贝构造函数创建x1吗?
Reply