当前位置: 首页 > 知识库问答 >
问题:

构造函数是否也有隐式this参数

端木宏才
2023-03-14

我正在学习C中的类,并且知道非静态成员函数具有隐式此参数。我的第一个问题是构造函数是否也像非静态成员函数一样具有隐式this参数。请注意,我不是在问我们是否可以在ctor中使用this,因为我已经知道我们可以在ctor中使用this

接下来,我知道在类X的限定非静态成员函数中,这个函数的类型是const X*。对于非静态成员函数(无const限定),此的类型为X*。类似地,在ctor中,此的类型始终是X*。更深层的问题来了。

我们知道,当我们调用一个非静态成员函数(例如likeobj.func())时,名为obj的对象的地址会隐式传递给方法func的隐式this参数。因此,这解释了“在非静态成员函数的情况下,此来自何处”。

现在,让我们将同样的事情应用于构造函数。例如,假设我们使用默认ctor创建一个类X的对象,如下所示:

X x; //does the default ctor also have an implicit this parameter to which the address of x is passed?

我的第二个问题是:同样的事情会发生在CTOR身上吗?与之类似,x的地址被传递给默认ctor的隐式参数。我目前的理解是,ctor没有隐式this参数。所以当我们写X时,x的地址未作为参数传递,因为对象尚未创建,因此传递其地址没有意义。但是从标准中我们知道,在一个向量中,我们可以使用这个指针。所以我的第二个问题本质上是,如果ctor没有隐式的this参数,那么语句this中的this在哪里-

struct Name 
{
    private:
         int p = 0;
         int k = 0;
    void func()  //func is a non-static member function and so have an implicit this parameter
    {
        this->k = 0; // the "this" here comes from implicit this parameter
    }
    Name()
    {
      this->p = 0;  //where does the "this" comes from here since ctor don't have implicit this parameter
    }
    
};

我的第三个问题是隐式this参数的概念是实现细节还是标准说非静态成员函数将有一个隐式this参数。

>

  • CTOR是否有隐式this参数?第一个问题也可以用“ctor是否也有隐式对象参数?”。

    标准说我们可以在ctor中使用this。但是this来自哪里。例如,在非静态成员函数的情况下,我们知道this来自隐式this参数,但在ctor的情况下,由于ctors没有隐式this参数,我们被允许在ctor中使用的this来自哪里。

    隐式this参数的概念是实现细节,还是标准规定所有非静态成员函数都有隐式this参数,在这种情况下,实现也允许ctor有隐式this参数。

    这个问题最重要的部分(IMO)是,我们如何在ctor中使用这个名称?例如,当我们写:

    this->p = 0; //here "this" behaves like a name
    

    在上面的语句中,此行为类似于名称。我们知道,在C中使用任何名称(如变量名)之前,必须对该名称进行声明。那么这个的声明在哪里呢?编译器在使用ctor时是否隐式声明了此代码?我的意思是,在非静态成员函数的情况下,我可以理解它们将this的声明作为隐式this参数,但是在ctors中会发生什么呢?在ctors内部,我们如何能够使用名称this而不需要声明?

  • 共有3个答案

    司空胤
    2023-03-14

    “this”是一个关键字;它不需要声明,但在非静态成员函数中始终可用。

    参见此处的标准草案。

    关键字this命名一个指针,指向调用隐式对象成员函数或计算非静态数据成员初始值设定项的对象。

    请注意,未指定此背后的机制。

    汪茂
    2023-03-14

    标准中没有“隐式此参数”这样的东西。该标准称之为“隐式对象参数”。

    隐式对象参数仅与重载分辨率相关,它不会“变成”此。此外,该定义为与成员职能部门具有相同的cv资格。

    CTOR是否有隐式this参数?第一个问题也可以用“ctor是否也有隐式对象参数?”。

    否,来自

    出于重载解析的目的,静态和非静态成员函数都有隐式对象参数,但构造函数没有。

    但是这是从哪里来的呢。

    正在构造的对象。

    隐式this参数的概念是实现细节还是标准说所有非静态成员函数都有一个隐式this参数,在这种情况下,实现也允许ctor有一个隐式this参数。

    隐式对象参数是重载解析规则的一部分,它不影响this

    在CTOR内部,我们如何能够在没有声明的情况下使用名称this?

    这不是一个名称,而是一个语言关键字。该语言将非静态成员函数中的此定义为prvalue表达式。与位于相同位置的非限定id(命名对象)不同,非限定id是glvalue表达式。

    这是语言律师的回答。话虽如此,我确实发现“隐式对象参数变成this”是一个有用的心理模型。

    回想一下,构造函数(和析构函数)不能被cv限定,所以在构造函数中没有任何东西可以区分,所以它是否存在并不重要。

    路扬
    2023-03-14

    该标准只描述了这个关键字的语义,而没有描述它的值是如何到达那里的。这是完全抽象的,实现在实现过程中具有很大的灵活性。

    正在构造的对象的地址,可以通过关键字this获得,绝对是对象初始化过程(C中称为“构造函数”)的输入。虚拟基子对象的地址也是如此,C也通过关键字this提供了这些地址,但不能从主输入中计算出来,因此任何这样的地址都必须是附加输入。

    请注意,与动态变量输入相比,CS倾向于在程序中使用“参数”,更像是模板参数。CS使用“功能”来表示无副作用的程序。C构造函数不是CS“函数”,虽然可以使用模板构造函数(参数化过程),但此的值是普通输入,而不是参数化。

    C构造函数也不是方法——不存在依赖于多态目标类型的分派,因此特别是此输入不用于分派。

    C构造函数是一个特殊的成员函数。无法为其构造函数指针或以C风格调用它;C函数的ABI要求不适用。

    如果平台ABI显式描述了C行为,那么将有一个或多个规则用于将this的值传递给C构造函数。这些规则可能会也可能不会指定等效于其他函数参数的机制,但每个针对该平台的符合ABI的C编译器都会根据构造函数的特殊规则的要求传递this值。

    值得注意的是,将此传递给构造函数的ABI并不需要等同于将此传递给其他(非特殊和非静态)成员函数的方式,尽管实际的ABI可能会对这两者使用相同的方法。

     类似资料:
    • 问题内容: 我有两个类,和,扩展了前一个类。 具有以下构造函数: 我将注意到所有实例变量都已设置为private。 同时,具有以下构造函数: 但是,这为我的构造函数引发了“找不到符号”错误。 我尝试使用,但是我的超类的私有范围阻止了这种情况。 我发现向我的构造函数中添加字段并允许我调用超级构造函数,但是我想知道是否存在一种无需在子类构造函数中传递其所有参数的情况下调用超级构造函数的方法? 问题答案

    • 问题内容: 在Java中调用基类构造函数是强制性的吗?在C ++中,它是可选的,所以我问这个问题。 当我扩展时,我得到这个错误: 那么,调用基本构造函数的目的是什么?当我创建对象时,基类的构造函数将调用&然后涉及到派生权。 问题答案: 如果您自己不调用no- args构造函数,则该隐式调用;如果该构造函数不存在,则无效。要求调用超构造函数的原因是,超类通常在构造后会处于其预期的状态,其中可能包含无

    • 问题内容: 警告#1:实际上这是一个潜在的两部分:首先,私有内部类的构造函数是否具有形式参数?如果是,为什么JLS拒绝呢?如果没有,怎么/为什么不呢? 注意事项2: 此问题不用于推测。 我仅在寻找 权威 答案。 默认构造函数在JLS 8.8.9 中定义,该声明(部分说明): 除了在 非私有 内部成员类中之外,默认构造函数没有形式参数,在默认情况下,默认构造函数隐式声明一个表示该类的立即封闭实例的形

    • 我有两个类:Date和Person Person有Date类的两个属性 案例1 类是与Person类分开的类。我有这段代码正常工作: 案例2:内部类(赋值要求) 我把作为Person的私有内部类 现在,上面的构造函数代码不再工作了。以下是错误消息: 说明资源路径位置类型由于某些中间构造函数调用人员,类型Person的封闭实例不可用。java/Wk03_Ch10_文件IO_Ch13_接口/Wk03_

    • 我正在尝试使用recyclerview和room库创建一个简单的ToDoList应用程序。在使用room和mvvm架构方面,我正在遵循android开发者代码实验室,我似乎遇到了困难。我已经设置了应用程序的每一层,但在尝试使用ViewModelProvider实例化ViewModel时出现了一个错误。下面是我的ViewModel类中的代码。 } 下面是我试图初始化ViewModel的main片段中

    • 我正在重构一个越来越大的android项目。运行lint使我能够在外部类和内部类之间访问JSME问题私有成员。考虑下面的例子 我得到消息了 应用问题解决方案会将源更改为 我现在有点困惑。直到现在,我还以为这个例子相当于 在这种情况下,我错了吗?还是这是棉绒的问题?