如何在构造函数中访问类变量以在不使用 C++ 中的 this 指针的情况下分配它们
Posted
技术标签:
【中文标题】如何在构造函数中访问类变量以在不使用 C++ 中的 this 指针的情况下分配它们【英文标题】:how to access class variable inside a constructor to assign them without using this pointer in C++ 【发布时间】:2019-10-19 15:57:56 【问题描述】:当类变量和参数名称相同时,如何不使用this
指针访问类变量并为其赋值?我在构造函数中使用了class_name::variable_name
,而不是指向对象的this
指针。
请参阅下面的代码以获得更好的理解。
#include<iostream>
using namespace std;
class abc
int x;
public:
abc(int x)
abc::x=x;
void prnt()
cout<<x;
;
int main(void)
abc A(2);
A.prnt();
return 0;
如果不使用this
指针,这怎么可能?
【问题讨论】:
您的问题是什么?你在问为什么abc::x=x;
有效吗?
我通过为参数使用不同的名称来完全避免名称冲突。在这种情况下,我将使用xx
或x_
作为参数。
您提出了两个问题。第一个(如何......不使用this
)在您的问题中得到回答。第二个不清楚,因为一个答案是“这是可能的,因为 C++ 标准允许它”。或许你可以更好地解释一下你感到困惑的地方?
【参考方案1】:
第 1 点:您实际上并没有两个 x
s。参数为x
。成员x
的全名是abc::x
。
第 2 点:编译器很聪明。
当他是周围唯一的 John 时,您可以打电话给 John Smith John,您周围的人通常可以弄清楚您指的是谁。在一个满是约翰的房间里,你可能需要使用他的全名。如果有多个 John Smith,您可能需要更进一步并使用 John Paul Smith。
在一个大房间里,如果其他约翰离得更远,你可以打电话给约翰保罗史密斯约翰。附近的每个人都会认为您指的是最近的约翰。如果他们错了,作为沟通者的你就必须更加明确。
编译器也在做同样的事情。默认行为是使用最接近的x
,即可见范围最窄的那个。那将是参数x
。如果您想使用更远的x
,请使用明确的名称。
注意事项:
虽然这种情况很容易避免并且容易产生错误,因此这是一个糟糕的决定,但您会发现不时需要更全面地限定标识符,例如当您想要调用派生类重写函数后派生类的基类。
相关,这是using namespace std;
是usually a bad idea 的原因之一。
【讨论】:
【参考方案2】:重命名该参数或成员和/或使用初始化列表(您应该在任何情况下这样做)。
abc(int x) : x(x)
我个人会将成员变量命名为m_x
,然后这样做
abc(int x) : m_x(x)
【讨论】:
【参考方案3】:首先:我会避免使用相同的名称,即使 t 是可能的。
第二:你应该初始化你的类的变量,而不是稍后在构造函数体内覆盖它们!如果不进行优化,这可能会导致对成员变量的默认构造函数进行不必要的调用。
大多数人使用编码约定来处理参数和成员变量,可能是这样的:
class abc
int x;
public:
abc(int x_): x x_ // use initializer list and not constructor body!
;
在初始化列表中,您可以对构造函数 parm 和成员 var 使用相同的名称。但如前所述,我个人不喜欢它!
作为来自 cmets 的提示: 您应该避免使用此答案中描述的保留标识符:What are the rules about using an underscore in a C++ identifier?
【讨论】:
请注意,使用单个下划线作为标识符前缀是潜在的危险。如果该标识符以大写字母开头(可能是首字母缩写词之类的),那么您将使用保留标识符,这是未定义的行为。最好使用尾随下划线而不是前导。【参考方案4】:实际上,您的代码可以在 MSVC 中编译、运行和工作(虽然我不确定它是否会)。但是,除了 cmets 中提出的(更好的)建议之外,您还可以使用初始化列表:
abc(int x) : x x
但我仍然会称这种“糟糕”的编码风格。
【讨论】:
以上是关于如何在构造函数中访问类变量以在不使用 C++ 中的 this 指针的情况下分配它们的主要内容,如果未能解决你的问题,请参考以下文章
如何创建只能由特定类使用的构造函数。 (C# 中的 C++ Friend 等效项)