C++之内部类与外部类(嵌套类)及友元
转载于:http://www.cnblogs.com/qzhforthelife/p/3226885.html
先上代码:
class Outer
{
public:
Outer(){m_outerInt=;}
private:
int m_outerInt;
public:
//内部类定义开始
class Inner
{
public:
Inner(){m_innerInt=;}
private:
int m_innerInt;
public:
void DisplayIn(){cout<<m_innerInt<<endl;}
} ;
//End内部类
public:
void DisplayOut(){cout<<m_outerInt<<endl;}
}; int main()
{
Outer out;
Outer::Inner in;
out.DisplayOut();
in.DisplayIn(); return ;
}
如上面代码所示,这种情况下,外部类与内部类其实联系并不大,外部类无非仅仅限定了内部类类名的作用域范围,完全可以加上Outer限定之后像使用任何其他类一样来使用内部类,Outer于Inner而言仅仅是一种命名空间。
提问:上面代码中,内部类(Inner)成员函数(比如DisplayIn)如何访问外部类(Outer)数据成员呢?
答:问这个问题之前,先要明白一个事实:将来你是在一个Inner实例对象上调用Inner的成员函数的,而所谓的“访问外部类数据成员”这种说法是不合理的,“外部类”及任何类,只是代码而已,是一种说明,从内存的角度来讲,程序运行起来之后,代码存储在代码区,所以应该问“如何访问外部类实例的数据成员”,如此,你得先有一个外部类实例(或者实例的指针),然后才能谈访问。
退一步讲,如果你不管三七二十一,直接在Inner的DisplayIn方法里加上这样一行:
m_outerInt=;
然后你编译、链接也都通过了(事实上这是不可能的),那么,在main函数中:
int main()
{
Outer::Inner in;
in.DisplayIn(); return ;
}
如果这样你都能正常运行,天理何在?DisplayIn中的m_outerInt到底是哪个实例的数据?
所以,为了避免这样荒唐的事情发生,语法层面就已经使得上述不可能发生:连编译都不会通过。
提问:把上面代码中的Inner设置为Outer的友元类之后,能解决问题吗?
答:该提问者都不仅犯了第一个提问者的错误,还误解了友元的含义。
友元举例:
class Inner; class Outer
{
public:
Outer(){m_outerInt=;}
private:
int m_outerInt;
public:
/*//内部类定义开始
class Inner
{
public:
Inner(){m_innerInt=1;}
private:
int m_innerInt;
public:
void DisplayIn(){cout<<m_innerInt<<endl;}
} ;
//End内部类*/
public:
void DisplayOut(){cout<<m_outerInt<<endl;}
friend Inner;
};
class Inner
{
public:
Inner(){m_innerInt=;}
private:
int m_innerInt;
public:
void DisplayIn(){cout<<m_innerInt<<endl;}
//友元影响的函数
void TestFriend(Outer out)
{
cout<<"Good Friend:"<<out.m_outerInt<<endl;
}
} ; int main()
{
Outer out;
out.DisplayOut();
Inner in;
in.DisplayIn();
in.TestFriend(out);
return ;
}
内部类如果想达到友元访问效果(直接通过实例或者实例指针来访问实例的非公有成员),是不需要另外再声明为friend的,原因不言自明:都已经是自己人了。
提问:内部类实例(作为外部类的数据成员)如何访问外部类实例的成员呢?
见如下代码:
#include <iostream>
#define METHOD_PROLOGUE(theClass, localClass) \
theClass* pThis = ((theClass*)((char*)(this) - \
offsetof(theClass, m_x##localClass))); \ using namespace std; class Outer
{
public:
Outer(){m_outerInt=;}
private:
int m_outerInt;
public:
//内部类定义开始
class Inner
{
public:
Inner(){m_innerInt=;}
private:
int m_innerInt;
public:
void DisplayIn(){cout<<m_innerInt<<endl;}
// 在此函数中访问外部类实例数据
void setOut()
{
METHOD_PROLOGUE(Outer,Inner);
pThis->m_outerInt=;
}
} m_xInner;
//End内部类
public:
void DisplayOut(){cout<<m_outerInt<<endl;}
}; int main()
{
Outer out;
out.DisplayOut();
out.m_xInner.setOut();
out.DisplayOut();
return ;
}
看main函数:程序执行完main函数第一句后,内存中便有了一个数据块,它存储着out的数据,而m_xInner也在数据块中,当然,&out和this指针(外部类)都指向该内存块的起始位置,而内部类代码中的this指针当然就指向m_xInner的起始内存了,offsetof(theClass, m_x##localClass)获得的便是m_xInner在该内存块中与该内存块起始地址(这正是out的地址)的距离(偏移),即内部类this-外部类this的差值(以字节为单位)这样,用内部类this减去其自身的偏移,便可得到pThis。有了out的地址,基本上可以对其为所欲为了,至于为何要有char*强转,可以go to definition of offsetof,可以看到其实现中有个关于char的转换。
C++之内部类与外部类(嵌套类)及友元的更多相关文章
- C#外部类、内部类(嵌套类)之间的成员访问特点
最近程序中需要用到多线程工作下的单例模式.而其多种实现方法中,利用内部类实现懒汉模式是一种值得推荐的方式.顺便也就对内部类和外部类之间的关系做了一下研究,总结如下(理解不困难,不粘贴代码了,有需要的留 ...
- 【C++】嵌套类、友元
黄邦勇帅 里面关于嵌套类的介绍我有疑惑.里面11.9说在创建一个外围类的对象时先执行嵌套类的构造函数然后再执行外围类的构造函数,析构函数则以相反的方式执行. 可是我编程实验了一下,创建外围类对象时并不 ...
- C++嵌套类(内部类与外部类)
在一个类中定义的类被称为嵌套类,定义嵌套类的类被称为外部类.; //不能访问 mytest::i = 10;//不能访问 } private: class mytest { int i; int j; ...
- C++中内部类访问外部类的私有成员
首先,如果不知道什么是内部类InnerClass的话,就没必要往下看了. 尝试在C++中模仿apple objective-c 的Grand Dispatch简化多线程编程时,使用了boost::fu ...
- 139、Java内部类之使用this访问外部类属性
01.代码如下: package TIANPAN; class Outer { // 外部类 private String msg = "Hello World !"; class ...
- JAVA 嵌套类和内部类
一.什么是嵌套类及内部类? 可以在一个类的内部定义另一个类,这种类称为嵌套类(nested classes),它有两种类型: 静态嵌套类和非静态嵌套类.静态嵌套类使用很少,最重要的是非静态嵌套类, ...
- 分析java 嵌套类与内部类
一.什么是嵌套类及内部类? 可以在一个类的内部定义另一个类,这种类称为嵌套类(nested classes),它有两种类型:静态嵌套类和非静态嵌套类.静态嵌套类使用很少,最重要的是非静态嵌套类 ...
- Java 嵌套类基础详解
目录 1. 什么是嵌套类? 2. 为什么要使用嵌套类? 3. 嵌套类的类型 4. 静态嵌套类 5. 非静态嵌套类 5.1 成员内部类 5.2 局部内部类 5.3 匿名内部类 6. 嵌套接口 1. 什么 ...
- Java基础 -- 嵌套类(非静态嵌套类、静态嵌套类)
可以将一个类的定义放在另一个类的内部定义,这样的类就被称为嵌套类,包含嵌套类的类被称为外部类(outer class),也可以叫做封闭类. 嵌套类可以分为两种: 静态嵌套类(Static Nested ...
随机推荐
- 1. 两数之和【Leetcode中国,by java】
给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用. 示例: 给定 nums = [2, 7, 11, 15], target ...
- 给eclipse安装color-theme插件
给eclipse安装color-theme插件 2016年03月22日 19:16:01 ming_love 阅读数:5193 标签: Eclipse Color Theme 更多 个人分类: jav ...
- jQuery实现checkbox(复选框)选中、全选反选代码
谁都知道 在html 如果一个复选框被选中 是 checked="checked". 但是我们如果用jquery alert($("#id").attr(&qu ...
- OJ错误命令解释
①Presentation Error (PE) : 虽然您的程序貌似输出了正确的结果,但是这个结果的格式有点问题. 请检查程序的输出是否多了或者少了空格(' ').制表符('\t')或者换行符('\ ...
- Thunder团队第三周 - Scrum会议7
Scrum会议7 小组名称:Thunder 项目名称:i阅app Scrum Master:胡佑蓉 工作照片: 邹双黛在照相,所以图片中没有该同学. 参会成员: 王航:http://www.cnblo ...
- apache 多端口访问 配置
使用本地ip:端口号,或者修改hosts文件+域名的方法来进行本地多站点web调试. 注意这里是用apache 不是iis 1: 安装好AppServ2.5.9软件,官网是:[url]http ...
- ajax 返回值问题
错误示例:function returnFlag(){ $.ajax({ type:"post", dataType:"json", data:JSON.str ...
- lintcode-33-N皇后问题
33-N皇后问题 n皇后问题是将n个皇后放置在n*n的棋盘上,皇后彼此之间不能相互攻击. 给定一个整数n,返回所有不同的n皇后问题的解决方案. 每个解决方案包含一个明确的n皇后放置布局,其中" ...
- Java-编译后出现$1.class、$2.class等多个class文件
部署代码的时候,由于自身技术不精和疏忽,导致查询数据没有正常显示, 排除法最后只能是放置部署文件时未包括多出来的$class文件.放上去之后果然好使了,才记录下这个问题... 这是因为在我们写的类中存 ...
- Qt单元测试(QTestLib)
版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt单元测试(QTestLib) 本文地址:http://techieliang.co ...