代码之家  ›  专栏  ›  技术社区  ›  Daniel

C++类默认构造函数

  •  1
  • Daniel  · 技术社区  · 16 年前

    早些时候,我问为什么这被认为是不好的:

    class Example
    {
     public: 
      Example(void);
      ~Example(void);
      void f() {}
    }
    
    int main(void)
    {
     Example ex(); // <<<<<< what is it called to call it like this?
    
     return(0);
    }
    

    现在,我明白它是在创建一个函数原型,而不是返回一个类型为Example的原型。不过,我仍然不明白为什么它在g++和MS VC++中都能工作。

    我的下一个问题是使用上述方法,这个调用有效吗?

    int main(void)
    {
     Example *e = new Example();
    
     return(0);
    }
    

    ?这和简单地调用示例e()有什么区别???就像我知道这是一个函数原型一样,但似乎有些编译器会原谅这一点,允许它调用默认构造函数?我也试过这个:

    class Example
    {
     private:
      Example();
    
     public:
      ~Example();
    };
    
    int main(void)
    {
     Example e1(); // this works
     Example *e1 = new Example(); // this doesn't
    
     return(0);
    }
    

    所以我有点困惑:(如果这个问题被问了一百万次,我很抱歉。

    5 回复  |  直到 16 年前
        1
  •  1
  •   Community CDub    8 年前

    这很容易,丹尼尔:

    Example *e = new Example();
    

    这看起来不像一个名为“示例”的函数,是吗?函数有一个返回值、一个名称和参数。上述内容如何与之相匹配?

    示例e1();//这行得通

    是的,因为你不创建任何实例 Example 任何地方。您只需告诉代码,在周围的命名空间中的某个地方定义了一个函数,并且您可能希望调用该函数。是的,为了返回Example的对象,确实需要创建一个实例。但这并不意味着在这一点上会出现实例。相反,当你调用函数时,它会在函数中创建一个实例。

        2
  •  5
  •   Johannes Schaub - litb    16 年前

    question 将有助于理解这种行为

        3
  •  1
  •   Kazade    16 年前

    嗯……好吧,这个:

    示例e1();

    不起作用。你可能认为它起作用了,或者一些编译器正在接受它,但它并没有创建一个名为e1的示例实例,它只是声明了一个函数原型。去掉括号,它就会按照你的意愿工作。

    这个:

    示例*e1=新示例();

    无法工作,因为构造函数是私有的。如果你将构造函数公开,它将在堆上创建对象,e1将是指向该对象的指针。完成该对象后,您需要将其删除。

        4
  •  1
  •   JaredPar    16 年前

    对于第一个问题,“new Example()”是否有效。是的,这是完全合法的C++代码。虽然要完全正确,你需要在从main()返回之前删除对象,否则会导致内存泄漏。

    例子:

    int main(void)
    {
     Example *e = new Example();
     delete e;
     return(0);
    }
    

    最后一个问题。行“Example e1();”是有效的,因为它声明了一个函数原型。这实际上并不会导致机器代码被执行(很可能是堆栈空间)。它只是说,有一个没有参数的函数原型,返回一个示例类型。

    第二条线肯定会失败。此时,您正试图实际执行示例的构造函数。这是不合法的,因为函数的可访问性是私有的,因此编译器错误。

        5
  •  0
  •   xtofl Adam Rosenfield    16 年前

    我认为你应该区分“this resolves”、“this compiles”、“this links”和“this works”,并试着像C++解析器/编译器/链接器一样思考,看看第一个例子

    Example e1(); // function prototype
    

    看起来像一个函数声明。语法分析器 这样理解它,所以你不能在上调用例如成员函数 e1 编译器将生成一个引用某个函数的符号(它还看不到),但由于该函数没有被使用,它不会抱怨。如果您添加此代码,它将:

    e1.f();// since e1 is a function, it has no member 'f' => compiler error
    

    (附带说明:此代码还将编译:

    int a_function_prototype(int); // another prototype.
    e1(); // should work!
    a_function_prototype(5);
    

    但是编译器完成后,链接器将开始查找实际的函数体,但找不到任何函数体。)

    现在自从线

    Example* e = new Example();
    

    包含关键字 new 编译器识别,并且它知道它只能在新对象的分配+构造中找到,它将生成代码来实现这一点。

    推荐文章