Теперь у меня есть код ниже:
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» &’существует, но недоступно.
На мой взгляд, правильно показывать ошибку, потому что это не как отношения, если используется личное наследство.
Но первый шаблон кода работает хорошо.
И мне интересно, почему?
Если вы замените частное наследование частным членом, вы получите точно такой же результат:
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()
не член или друг; попытайся :
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;
}
Сейчас это компилируется.
Ваш Instance()
метод сломан, вы должны иметь только 1 static
объект:
static Env* Instance()
{
static CEnv instance;
return &instance;
}
Или ссылочный случай:
static Env& Instance()
{
static CEnv instance;
return instance;
}
Частное наследование — это отношение «есть», которое является секретом для всех, кроме самого наследующего класса.
Внутри вашего CEnv
класс, наследование «известно» (частное наследование было бы в основном бесполезным, если бы наследующему классу было запрещено знать об этом).
Таким образом, преобразование из CEnv*
в Env*
в CEnv::Instance
действителен, так как это CEnv
это делает преобразование.
test
функция не является членом CEnv
поэтому, с его точки зрения, конвертация не разрешена.