在C ++中解释空类函数 [英] Explain blank class functions in C++

查看:194
本文介绍了在C ++中解释空类函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 类论坛:public master {
public:
forums():next(0),prev(0){}
}




  1. 请说明下一个函数(0)是什么意思?


  2. 用逗号(,)表示函数的分隔是什么意思?
    这些函数旁边有空括号{}的效果?


  3. 我是C ++的初学者,


这是意味着还是打算用于这些写作功能? p>

解决方案

简短答案



这是一个具有空体的构造函数,将 0

$

$初始化两个数据成员的成员初始化列表



ie




  • class-name([ctor-args])[:member-init-list] [ctor-body]}


  • 其中 member-init-list 成员名称(args)[, ul>

    (注意:不是实际的C ++词法语法结构)






    长回答



    背景



    采取以下类别定义:

      struct Base {}; 
    struct Derived:Base {};

    您可能已经注意到 Derived



    您也可能已经注意到派生 Base 都有一个合成的(隐式声明)默认(不带参数)构造函数。 派生的的构造函数隐式/自动调用 Base 的。



    现在让我们添加一个基本的成员函数:

      struct Derived:Base {
    void foo
    };

    我已经宣布定义了这个成员函数 foo ;它的主体是空的,所以当你调用它没有什么发生。这是非常无意义的,但它是完全有效的。



    现在,让我们自己的构造函数:

      struct Derived:Base {
    Derived(){}
    };

    这看起来更熟悉。它仍然是一个具有空体的[特殊]函数, Base 构造函数仍然被隐式调用。



    b b b b >让我们在构造函数中添加一些数据成员并设置它们的值:

      struct Derived:Base {
    Derived {
    x = 0;
    y = 0;
    }

    int x,y;
    };

    x y 将在对象构造之后具有值 0 。这仍然是基本的C ++。



    但你可以不要知道的是,你不是初始化这些数据成员。



    事实上,内置类型的数据成员不是隐式初始化的,所以让我们选择一个更好的例子:

      struct Derived:Base {
    Derived()/ * HERE * / {
    x =;
    y =;
    }

    std :: string x,y;
    };

    y 在构造函数体中运行的代码之前隐式初始化。当构造函数体开始运行时,所有要初始化的成员都已经初始化,并且基础构造函数已被隐式调用。



    我们可以通过在我写的地方写成员初始化列表来拦截这种行为并提供我们自己的初始化值 / * HERE * / 。使用成员初始化列表,代码片段如下所示:

      struct Derived:Base {
    Derived (),y(){
    x =;
    y =;
    }

    std :: string x,y;
    };

    哇!好;现在我们将字符串初始化为,稍后在构造函数体中为它们分配相同的空值。我们可以删除这些任务,然后:

      struct Derived:Base {
    Derived():x ),y(){}

    std :: string x,y;
    };

    现在构造函数体是空的,它隐式调用基础构造函数,并且显式地初始化数据成员 x y



    因为 std :: string 有一个默认的构造函数,可以写成:

      struct Derived:Base {
    Derived():x }

    std :: string x,y;
    };

    回到原始示例,这同样适用于内置类型的对象。让我们考虑两个指针:

      struct Derived:Base {
    Derived():next ){}

    Derived * next;
    Derived * prev;
    };






    处理基类



    并且,作为一个额外的好处,我们可以使用成员初始化列表来显式调用基础构造函数:

      struct Derived:Base {
    Derived():Base(),next(0),prev(0){}

    Derived *
    Derived * prev;
    };

    除非基础构造函数需要一些参数,否则这是很无意义的:

      struct Base {
    Base(int x){}
    };

    struct Derived:Base {
    Derived():Base(0),next(0),prev(0){}

    Derived * next;
    Derived * prev;
    };






    我希望这是有用的。 p>

    class forums : public master{
    public:
        forums() : next(0),prev(0) {}
    }
    

    1. Please Explain what exactly does the functions next(0) and prev(0) are meant?

    2. What does seperation of function with a comma (,) indicates? what's the effect of empty braces {}, next to these functions?

    3. I am a beginner in C++, and trying to figure out what does this means, or intended use for these way of writing function?

    like is it specially meant for overriding?

    解决方案

    Short answer

    That is a constructor with an empty body, and a member initialisation list that initialises two data members to the value 0.

    i.e.

    • class-name([ ctor-args ]) [ : member-init-list ] { [ ctor-body ] }

    • where member-init-list is member-name(args) [, member-name(args) [, ... ] ].

    (Note: not actual C++ lexical grammar constructions)


    Long answer

    Background

    Take the following class definitions:

    struct Base {};
    struct Derived : Base {};
    

    You may already be aware that Derived derives from Base.

    You may also already be aware that Derived and Base both have a synthesised (implicitly-declared) default (takes no arguments) constructor. Derived's constructor implicitly/automatically invokes Base's.

    Now let's add a basic member function:

    struct Derived : Base {
       void foo() {}
    };
    

    I have both declared and defined this member function foo; its body is empty, so nothing happens when you invoke it. This is pretty pointless, but it's perfectly valid.

    Now, instead, let's make our own constructor:

    struct Derived : Base {
       Derived() {}
    };
    

    This looks more familiar. It's still a [special] function with an empty body, and the Base constructor is still being implicitly invoked. We haven't changed that.


    Handling data members

    Let's add some data members and set their value in our constructor:

    struct Derived : Base {
       Derived() {
          x = 0;
          y = 0;
       }
    
       int x, y;
    };
    

    Both x and y will have the value 0 after object construction. This is still fundamental C++.

    But what you may not be aware of is that you are not initialising these data members. You are merely assigning to them after the possibility of initialising them.

    In fact, data members of built-in types are not implicitly initialised, so let's pick a better example:

    struct Derived : Base {
       Derived() /* HERE */ {
          x = "";
          y = "";
       }
    
       std::string x, y;
    };
    

    x and y are implicitly initialised before the code in the constructor body runs. When the constructor body starts to run, all members that will be initialised, have already been initialised, and the base constructor has been implicitly invoked.

    We can intercept this behaviour and provide our own initialisation values by writing a member initialiser list in the place where I wrote /* HERE */ in the previous snippet. With the member initialiser list, the snippet looks like this:

    struct Derived : Base {
       Derived() : x(""), y("") {
          x = "";
          y = "";
       }
    
       std::string x, y;
    };
    

    Wow! OK; now we're initialising the strings to "", and later assigning the same, empty value to them in the constructor body. We can get rid of those assignments, then:

    struct Derived : Base {
       Derived() : x(""), y("") {}
    
       std::string x, y;
    };
    

    Now the constructor body is empty, but the constructor still does stuff. It implicitly invokes the base constructor, and it explicitly initialises the data members x and y to the empty string.

    And, because std::string has a default constructor that does the same, we can write for short:

    struct Derived : Base {
       Derived() : x(), y() {}
    
       std::string x, y;
    };
    

    Going back to your original example, this applies to objects of built-in types just as easily. Let's consider two pointers:

    struct Derived : Base {
       Derived() : next(0), prev(0) {}
    
       Derived* next;
       Derived* prev;
    };
    


    Handling base classes

    And, as an added bonus, we can use the member initialisation list to invoke the base constructor explicitly:

    struct Derived : Base {
       Derived() : Base(), next(0), prev(0) {}
    
       Derived* next;
       Derived* prev;
    };
    

    This is pretty pointless unless the base constructor wants some arguments:

    struct Base {
       Base(int x) {}
    };
    
    struct Derived : Base {
       Derived() : Base(0), next(0), prev(0) {}
    
       Derived* next;
       Derived* prev;
    };
    


    I hope that this has been useful.

    这篇关于在C ++中解释空类函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆