私有继承和从函数返回引用
Private inheritance and returning references from functions
现在我有以下代码:
class Env
{
public:
int ra(){ return a;}
int rb(){ return b;}
private:
int a;
int b;
};
class CEnv: private Env
{
public:
static Env* Instance()
{
CEnv* pEnv = new CEnv;
return pEnv;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Env* pEnv = CEnv::Instance();
pEnv->ra();
return 0;
}
它有效well.Later我添加了一些代码。
class Env
{
public:
int ra(){ return a;}
int rb(){ return b;}
private:
int a;
int b;
};
class CEnv: private Env
{
public:
static Env* Instance()
{
CEnv* pEnv = new CEnv;
return pEnv;
}
};
Env* test()
{
CEnv *p = new CEnv;
return p;
}
int _tmain(int argc, _TCHAR* argv[])
{
Env* pEnv = CEnv::Instance();
pEnv->ra();
return 0;
}
然后VS2010会报编译错误:
错误 C2243:'type cast':存在从 'CEnv *' 到 'Env &' 的转换,但无法访问。
在我看来,显示错误是正确的,因为如果使用私有继承,它就不是一种关系。
但是第一个代码模式运行良好。
我想知道为什么?
您的 Instance()
方法已损坏,您应该只有 1 个 static
对象:
static Env* Instance()
{
static CEnv instance;
return &instance;
}
或者,参考案例:
static Env& Instance()
{
static CEnv instance;
return instance;
}
私有继承是一种 "is-a" 关系,除了继承 class 本身之外,每个人都是秘密的。
在您的 CEnv
class 中,继承是 "known"(如果不让继承 class 知道私有继承,那么私有继承将毫无用处) .
因此,CEnv::Instance
中从 CEnv*
到 Env*
的转换是有效的,因为是 CEnv
进行了转换。
test
函数不是 CEnv
的成员,因此从它的角度来看不允许转换。
如果将私有继承替换为私有成员,您将得到完全相同的结果:
class Env
{ /* whatever */
};
class CEnv{
private:
Env m;
public:
static Env *Instance()
{
CEnv *pEnv = new CEnv; /* memory leak */
return &pEnv->m;
}
};
(忘记内存泄漏,因为这只是为了说明目的。)
这里可以访问成员 因为 Instance()
是 class.
的成员
具有non-member函数:
Env *test()
{
CEnv *p = new CEnv;
return &p->m;
}
函数 test()
不是成员或朋友; try it :
prog.cpp: In function 'Env* test()':
prog.cpp:7:13: error: 'Env CEnv::m' is private
Env m;
^
prog.cpp:20:20: error: within this context
return &p->m;
^
如有必要,请加为好友:
class CEnv2 {
private:
Env m;
friend Env *::test2();
};
Env *test2()
{
CEnv2 *p = new CEnv2;
return &p->m;
}
现在it compiles.
现在我有以下代码:
class Env
{
public:
int ra(){ return a;}
int rb(){ return b;}
private:
int a;
int b;
};
class CEnv: private Env
{
public:
static Env* Instance()
{
CEnv* pEnv = new CEnv;
return pEnv;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Env* pEnv = CEnv::Instance();
pEnv->ra();
return 0;
}
它有效well.Later我添加了一些代码。
class Env
{
public:
int ra(){ return a;}
int rb(){ return b;}
private:
int a;
int b;
};
class CEnv: private Env
{
public:
static Env* Instance()
{
CEnv* pEnv = new CEnv;
return pEnv;
}
};
Env* test()
{
CEnv *p = new CEnv;
return p;
}
int _tmain(int argc, _TCHAR* argv[])
{
Env* pEnv = CEnv::Instance();
pEnv->ra();
return 0;
}
然后VS2010会报编译错误: 错误 C2243:'type cast':存在从 'CEnv *' 到 'Env &' 的转换,但无法访问。
在我看来,显示错误是正确的,因为如果使用私有继承,它就不是一种关系。 但是第一个代码模式运行良好。 我想知道为什么?
您的 Instance()
方法已损坏,您应该只有 1 个 static
对象:
static Env* Instance()
{
static CEnv instance;
return &instance;
}
或者,参考案例:
static Env& Instance()
{
static CEnv instance;
return instance;
}
私有继承是一种 "is-a" 关系,除了继承 class 本身之外,每个人都是秘密的。
在您的 CEnv
class 中,继承是 "known"(如果不让继承 class 知道私有继承,那么私有继承将毫无用处) .
因此,CEnv::Instance
中从 CEnv*
到 Env*
的转换是有效的,因为是 CEnv
进行了转换。
test
函数不是 CEnv
的成员,因此从它的角度来看不允许转换。
如果将私有继承替换为私有成员,您将得到完全相同的结果:
class Env
{ /* whatever */
};
class CEnv{
private:
Env m;
public:
static Env *Instance()
{
CEnv *pEnv = new CEnv; /* memory leak */
return &pEnv->m;
}
};
(忘记内存泄漏,因为这只是为了说明目的。)
这里可以访问成员 因为 Instance()
是 class.
具有non-member函数:
Env *test()
{
CEnv *p = new CEnv;
return &p->m;
}
函数 test()
不是成员或朋友; try it :
prog.cpp: In function 'Env* test()':
prog.cpp:7:13: error: 'Env CEnv::m' is private
Env m;
^
prog.cpp:20:20: error: within this context
return &p->m;
^
如有必要,请加为好友:
class CEnv2 {
private:
Env m;
friend Env *::test2();
};
Env *test2()
{
CEnv2 *p = new CEnv2;
return &p->m;
}
现在it compiles.