为什么C++中复制构造函数可以调取其他对象中的私有变量

私有成员变量的概念,在脑海中的现象是,以private关键字声明,是类的实现部分,不对外公开,不能在对象外部访问对象的私有成员变量.

然而,在实现拷贝构造函数和赋值符函数时,在函数里利用对象直接访问了私有成员变量,因而,产生了困惑.下面以具体实例进行说明:

疑惑:为什么第26行和第32行代码可以编译通过,而第39行和第40行代码会产生编译错误?

 1 class CTest {
 2 public:
 3     CTest(int i);
 4     CTest(const CTest& rhs);
 5     CTest& operator=(const CTest& rhs);
 6     void printCTest(const CTest& rhs);
 7 private:
 8     int value;
 9 };
10
11 CTest::CTest(int i):value(i)
12 {
13     cout<<"Contructor of CTest"<<endl;
14 }
15
16 CTest::CTest(const CTest& rhs):value(rhs.value)
17 {
18     cout<<"Copy contructor of CTest"<<endl;
19 }
20
21 CTest& CTest::operator=(const CTest& rhs)
22 {
23     cout<<"Assign function of CTest"<<endl;
24     if(this == &rhs)
25         return *this;
26     value = rhs.value;                //通过对象访问私有成员变量
27     return *this;
28 }
29
30 void CTest::printCTest(const CTest& rhs)
31 {
32     cout<<rhs.value<<endl;        //通过对象访问私有成员变量
33 }
34
35 int main()
36 {
37     CTest t = 1;
38     CTest tt = 2;
39     //  cout<<t.value<<endl;        //通过对象访问私有成员变量,编译错误
40     //  cout<<tt.value<<endl;        //通过对象访问私有成员变量,编译错误
41     t.printCTest(tt);
42 }  

产生这种疑惑的原因是自己对私有成员变量的理解有误,封装是编译期的概念,是针对类型而非对象的,在类的成员函数中可以访问同类型实例对象的私有成员变量

具体的解析如下:从变量value的符号是怎么解析的分析

1.确定符号的查找域

如第26行代码,当编译器发现value变量时,它会在value变量所属的对象rhs的类域中寻找该符号.

2.确定当前域中哪些符号可以访问

由第1步可知,当前查找的域是类域,而printCTest函数在CTest类体中,所以printCTest可以访问CTest类中的所有变量(包括私有成员变量),因而value符号在CTest类域中被找到.

如第39行代码,main函数不在CTest类体中,所以main函数不可以访问CTest类域中的私有成员变量.

3.符号已查找到,编译通过

类成员变量的访问权限是编译器强加的,编译器可以找到value,通过编译,自然就可以访问到value变量的值.

直觉上,我们会以为第26行代码中value符号的查找域应该是对象rhs对应的作用域,然而C++编译器的实现却是在对象rhs的类域查找value符号.

启发:有些直觉是靠不住的,需要深入分析其背后的实现原理,才可以理解透彻.

原文地址:https://www.cnblogs.com/woshizhizhong-tech/p/8450475.html

时间: 2024-10-07 02:23:34

为什么C++中复制构造函数可以调取其他对象中的私有变量的相关文章

javascript中的闭包、模仿块级作用域和私有变量

闭包是指有权访问另一个函数作用域中的变量的函数.创建闭包的常见方式为:在一个函数内部创建另一个函数. "当某个函数被调用时,会创建一个执行环境(execution context)及相应的作用域链.然后,使用arguments和其他命名参数的值来初始化函数的活动对象(activation object).但在作用域链中,外部函数的活动对象始终处于第二位,外部函数的外部函数的活动对象出于第三位.....直至作用域链终点的全局执行环境." function creawteCompariso

C++中复制构造函数被调用的三种情况

C++中的构造函数 c++中的构造函数分为构造函数,和复制构造函数,相比于构造函数,复制构造函数使用更加方便,快捷.构造函数可以有多个,二复制构造函数只能有一个,因为复制构造函数的参数只能是当前类的一个对象,参数表是固定的,无法重载,若用户没有定义自己的辅助构造函数,系统会自动生成一个复制构造函数,其作用是将参数的之赋予当前的对象.若用户自己定义了复制构造函数,系统则不会生成默认复制构造函数.用户自己定义的复制构造函数功能可以自己构造,不一定执行复制的功能. 复制构造函数同构造函数的功能大体相同

AutoCAD.Net/C#.Net QQ群:193522571 从已有A.DWG中复制块BLK到新DWG中的方法

1.新建一个Database,new Database(true, false); 2.以A.DWG为原型新建一个Database,new Database(false,true); 3.将2中的块表记录复制到1的块表中: 4.新建一个块参照,new BlockReference(blockReferencePoint, blocoId); 5.插入到1的Database中,InsertBlockReference(db, blockReference); 对于已有的DWG:new Databa

如何从word中复制内容到网站后台编辑器中

word图片转存,是指UEditor为了解决用户从word中复制了一篇图文混排的文章粘贴到编辑器之后,word文章中的图片数据无法显示在编辑器中,也无法提交到服务器上的问题而开发的一个操作简便的图片转存方案. <b>复制word图文混排内容到UEditor,图片不能正常显示,会将图片转换成一个带链接的占位图,如图 并且图片地址也是本地的路径,如果直接发布内容后,其它的用户将看不到图片(也就是不能正常访问图片,因为图片的路径不正确) 解决办法: 拷贝图片链接->点击上传图片->选择网

vue中computed计算属性与methods对象中的this指针

this 指针问题 methods与computed中的this指针 应该指向的是它们自己,可是为什么this指针却可以访问data对象中的成员呢? 因为new Vue对象实例化后data中的成员和computed中的成员为实现化对象属性了,而methods中定义的方法为实现化对象方法了.这时this指针指向的是这个实现化对象. let v = new Vue({ el: '.test', data: { title: "121213" }, methods: { msg() { al

c++中六种构造函数的实现以及9中情况下,构造函数的调用过程

六种构造函数的实现代码如下: #include<iostream> using namespace std; //c++中六种默认的构造函数 class Test { public: Test(int d = 0):m_data(d)//1构造函数(带默认值0),以参数列表的形式初始化 { cout<<"Creat Test Obj :"<<this<<endl; } ~Test()//2析构函数 { cout<<"

如何从一个DataTable中复制数据行到另一个DataTable中

DataTable dt = ""; //这里是填充DataTable数据 DataTable dtNew = dt.Copy(); //复制dt表数据结构 dtNew.Clear() //清楚数据 for (int i = 0; i < dt.Rows.Count; i++) { if (条件语句) { dtNew.Rows.Add(dt.Rows[i].ItemArray); //添加数据行 } } ===前提:我们已经有一个DataTable的数据表 现在需要的只是其中的一

C++返回值为对象时复制构造函数不执行怎么破

先说点背景知识,调用复制构造函数的三种情况: 1.当用类一个对象去初始化另一个对象时. 2.如果函数形参是类对象. 3.如果函数返回值是类对象,函数执行完成返回调用时. 在辅导学生上机时,有同学第3点提出异议.有教材上的例题为证: #include <iostream> using namespace std; class Point //Point 类的定义 { public: Point(int xx=0, int yy=0) { x = xx; //构造函数,内联 y = yy; } P

C++ Primer 学习笔记_54_类与数据抽象 --复制构造函数、赋值操作符

复制控制 --复制构造函数.赋值操作符 引言: 当定义一个新类型时,需要显式或隐式地指定复制.赋值和撤销该类型的对象时会发生什么– 复制构造函数.赋值操作符和析构函数的作用!      复制构造函数:具有单个形参,该形参(常用const修饰)是对该类类型的引用.当定义一个新对象并用一个同类型的对象对它进行初始化时,将显式的使用复制构造函数:当将该类型的对象传递给函数或者从函数返回该类型的对象时,将隐式使用复制构造函数.     析构函数:作为构造函数的互补,当对象超出作用域或动态分配的对象被删除