现在我有以下代码:
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;
}
它运作良好。后来我添加了一些代码。
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:'输入' :转换自' CEnv *'到' Env&'存在,但无法访问。
在我看来,显示错误是正确的,因为如果使用私人遗嘱,它不是一种关系。 但第一个代码模式效果很好。 我想知道为什么?
答案 0 :(得分:1)
如果用私有成员替换私有继承,您将得到完全相同的结果:
class Env
{ /* whatever */
};
class CEnv{
private:
Env m;
public:
static Env *Instance()
{
CEnv *pEnv = new CEnv; /* memory leak */
return &pEnv->m;
}
};
(忘记内存泄漏,因为这仅用于说明目的。)
此处可以访问该成员,因为Instance()
是该类的成员。
使用非成员函数:
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。
答案 1 :(得分:0)
您的Instance()
方法已损坏,您应该只有1 static
个对象:
static Env* Instance()
{
static CEnv instance;
return &instance;
}
或者,参考案例:
static Env& Instance()
{
static CEnv instance;
return instance;
}
答案 2 :(得分:0)
私有继承是一种“is-a”关系,除了继承类本身之外,它是每个人的秘密。
在CEnv
类中,继承是“已知的”(如果不允许继承类知道它,则私有继承将是无用的)。
因此,CEnv*
中从Env*
到CEnv::Instance
的转换是有效的,因为它是进行转换的CEnv
。
test
函数不是CEnv
的成员,因此从其角度来看,不允许转换。