私有继承和从函数返回引用

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.