最后更新于 .

用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();

这行语句根本就是一行函数声明啊。。。 试想一下,有一天一个类的构造函数从一个参数变成空参数,于是你在调用的时候只是把括号里的参数删了,而括号还留着的话。。估计够你调几个小时了。。

Pingbacks

Pingbacks已打开。

Trackbacks

引用地址

评论

  1. WeAiM

    WeAiM on #

    我***。这个,要是没见过,不会想到这个。唉,一方面是对c++越来越不熟悉了,另一方面,这个实在太dt了。

    Reply

  2. sw

    sw on #

    看看这个:

    int b;
    C x1(C2(b));

    很遗憾的告诉你,这仍然是函数声明 :D

    Reply

    1. Dante

      Dante on #

      还真是。。。
      int b;
      C x1(C(b));

      Reply

  3. 一念天堂

    一念天堂 on #

    这个倒是一眼就看出来了,吃过这个亏,我也记得有大牛说过:这是语言的阴暗面之一,我们只能 live with it.

    Reply

    1. Dante

      Dante on #

      语义的二义性。。确实如此。。

      Reply

  4. fanhe

    fanhe on #

    c++ primer 说过了, 类类型的声明不能这样的初始化语法的.
    c++ 很多细节要注意的, 非常麻烦.

    Reply

  5. dutor

    dutor on #

    倒不觉得奇怪,如果之前是写Java的话就另说了。
    从语法分析的角度来讲,C x1();本就可以有两种解释,只不过C++优先把它当成函数声明罢了。

    Reply

    1. Dante

      Dante on #

      我不用java。。
      嗯,语义出现二义性了。

      Reply

    2. Fangzhen

      Fangzhen on #

      C++和java不一样,
      C x1()就是一个函数声明,C++中如果要使用默认构造函数(就是不带参数的构造函数)的时候不用加括号。如果要动态构造一个类的话加不加括号都一样,如:
      C * px=new C();
      和C *p=new C;
      是一样的

      Reply

  6. DJ

    DJ on #

    还真遇到过,不过那时候立刻调试了,一下发现没进去就明白是当成声明了

    Reply

  7. egmkang

    egmkang on #

    哇,居然还有这个,倒真的没碰到过............

    Reply

  8. egmkang

    egmkang on #

    C++真是到处都是坑啊

    Reply

  9. Shiina Luce

    Shiina Luce on #

    ……这是Java写多了吧

    Reply

    1. Dante

      Dante on #

      我还真不用java。。

      Reply

  10. sanitizer

    sanitizer on #

    隐约记得好像C++没参数的时候,推荐使用C(void)的吧?C()算是不规范写法。

    Reply

    1. Dante

      Dante on #

      C(void) 也是不行的。。你可以试试。
      void也可以看作是函数形参。

      Reply

    2. dutor

      dutor on #

      C里面C()原型可以传参,C++里面C()等价于C(void),这里面如果写成C(void)的话,就告诉编译器这就是原型,编译器就毫不犹豫咯。
      下面的“匿名”兄弟太有喜感了,哈哈哈

      Reply

  11. 0

    0 on #

    你不会用就别乱说,真是笑死人了!你怎么不用C x1=new C();这种方式去初始化C++代码?那岂不是更有喜剧效果?

    Reply

    1. shade

      shade on #

      这位匿名的兄台~
      我觉得你更搞笑一些
      希望你能分享一些有营养的内容~

      Reply

  12. 0

    0 on #

    真搞笑,用其他语言的语法去要求C++

    Reply

  13. 匿名

    匿名 on #

    C()调用的是拷贝构造函数,不是无参构造函数。不要在这种基本的问题是误导新手。

    Reply

    1. Dante

      Dante on #

      这位朋友,虽然你的几个评论都有点尖锐,但我开始还是不打算回复你的帖子的,但是你非要说C()居然是调用拷贝构造函数这种误导性的话,我只能出来辟谣了。

      C x1;
      C x2(x1);
      C x3 = x1;
      x3 = x2;

      这几行代码,你能正确的说出都调用了什么函数吗?

      Reply

      1. Sunday

        Sunday on #

        唉,不要和此种人一般见识,无知就算了,出来让别人笑话就是他的问题了 !

        Reply

        1. Dante

          Dante on #

          哈哈,多谢支持~~~~

          Reply

  14. Huarong

    Huarong on #

    一直都用new的飘过。

    Reply

  15. niuniu

    niuniu on #

    哈哈 还真是如此~
    如果C++滴水不漏,就不会有其他语言了~

    Reply

  16. 1901

    1901 on #

    上帝保佑我以后不要遇到这个问题,我经常写AS的啊!

    Reply

  17. dreamersdw

    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

    1. Dante

      Dante on #

      确实如此,说C顶多砸到脚,C++不小心就会炸飞整条腿的比喻真是非常贴切。

      我现在写自己的东西都是python,简洁优雅。

      可惜公司代码只能用C++,无奈。。。

      Reply

    2. springlie

      springlie on #

      貌似这个问题在Effective 系列中提过。。。

      Reply

      1. t.w.

        t.w. on #

        这个问题我也奇怪过
        原来果然是和函数声明一样啊

        Reply

  18. 夜弓

    夜弓 on #

    嗯,在c++里面,一个语句如果可以是函数声明,那么它就是函数声明。

    Reply

    1. Sunday

      Sunday on #

      应该是这么回事~C++时间越长,越觉得杯具~

      Reply

  19. johnson

    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

    1. Dante

      Dante on #

      朋友,你还是再回去看看C++的书吧。

      Reply

  20. t.w.

    t.w. on #

    这个问题我也奇怪过,看了你的才理解原因,原来果然是和函数声明一样啊~

    Reply

  21. t.w.

    t.w. on #

    这个问题我也奇怪过,看了你的才理解原因,原来果然是和函数声明一样啊

    Reply

  22. t.w.

    t.w. on #

    这个问题我也奇怪过,
    看了你的才理解原因,
    原来果然是和函数声明一样啊

    Reply

  23. xheruacles

    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

  24. Terrence

    Terrence on #

    的确如此,有些时候人的视角和编译器的视角是不是不一致的。习惯就好~

    Reply

  25. IMS

    IMS on #

    如果函数声明使用了C(void){}这样呢?

    Reply

  26. cplusplusisapieceofshit

    cplusplusisapieceofshit on #

    之前学过一点c++皮毛,然后学过java之后想再回头好好学习下c++,因为觉得c++还是很牛的,但每次看个开头就看不下去了,相比java,c++就是一坨屎一样的恶心。

    Reply

  27. lssb

    lssb on #

    C++是一门优秀的语言,优秀不代表完美,总会存在或多或少的不习惯。但C++能流行30多年,足以说明一切问题了, ls的那个不懂就不要在那装B ,你说的话更相一坨屎

    Reply

  28. d

    d on #

    第一次遇到这个是在面试的时候,于是面试惨败

    Reply

  29. haoaina521

    haoaina521 on #

    看完评论才知道这是函数声明,并不是有参数和无参数的区别。向楼主请教两个问题,如果问题有错,麻烦指出下:1.C c;这句语句是变量的定义?在定义的时候初始化了?2.C* pC1 = new C;和C* pC2 = new C();有什么不同?

    Reply

  30. helloworld

    helloworld on #

    求教,为什么是函数声明?另外,这句代码的原义是以b为参数构造一个C的对象,然后调用拷贝构造函数创建x1吗?

    Reply

发表评论