Алмазное наследование со смешанными модификаторами наследования (защищенное/частное/общедоступное)

скажем, у нас есть class A,B,C,D, где A — основание, B, C — между ними, а D получено в модели алмаза.

ПРИМЕЧАНИЕ.

class B наследует виртуально class A в частном режиме,

class C наследует виртуальный class A в защищенном режиме.

class A
{
public:
    int member;  // note this member
};
class B :
    virtual private A // note private 
{

};
class C :
    virtual protected A // note protected
{

};
class D :
    public B, // doesn't metter public or whatever here
    public C
{

};

int main()
{
    D test;
    test.member = 0; // WHAT IS member? protected or private member?
    cin.ignore();
    return 0;
}

теперь, когда мы создадим экземпляр class D, каким будет член? частный или защищенный лол?

Рис. 2.

а если сделать так:

class B :
    virtual public A // note public this time!
{

};
class C :
    virtual protected A // same as before
{

};

Я полагаю, что member будет общедоступным во втором примере, не так ли?


person codekiddy    schedule 21.01.2012    source источник


Ответы (1)


§11.6 Multiple access [class.paths]

Если имя может быть достигнуто несколькими путями через граф множественного наследования, доступом является тот путь, который дает наибольший доступ. [ Пример:

class W { public: void f(); };
class A : private virtual W { };
class B : public virtual W { };
class C : public A, public B {
   void f() { W::f(); } // OK
};

Поскольку W::f() доступен для C::f() по общедоступному пути через B, доступ разрешен. —конец примера ]

Думаю, мне больше не нужно ничего добавлять, но см. также этот отчет о дефекте (который был закрыт как "не являющийся дефектом").

person Xeo    schedule 22.01.2012
comment
@Kerrek: Спасибо за редактирование, я не мог вспомнить, как легко вставлять код в цитату. :) - person Xeo; 22.01.2012
comment
Это я говорил в своем предыдущем комментарии: D у публичного больше власти, чем у частного или защищенного. хороший пример большое спасибо. но это не относится к комбинации PRIVATE/PROTECTED! список наследования имеет большую силу в этом случае :) круто. - person codekiddy; 22.01.2012
comment
@codekiddy: я не совсем понимаю. Если бы пример был изменен с public virtual/private virtual на protected virtual/private virtual, поведение осталось бы таким же - вызов W::f() был бы разрешен из-за защищенного пути доступа через B - порядок в списке наследования (список базового класса) не имеет ничего общего с чем угодно, насколько я могу видеть. - person Xeo; 22.01.2012
comment
Извините, я говорил о вызове функции f() из экземпляра объекта C (в вашем примере) в функции main! не вызывая внутри класса, такого как W::F(): D вызовите его из экземпляра, и вы увидите, хе-хе - person codekiddy; 22.01.2012
comment
ДОБАВЬТЕ: удалите функцию f() {(W::f(); } и вызовите ее из экземпляра C или скопируйте мой первый пример! - person codekiddy; 22.01.2012
comment
@codekiddy: Ну конечно. Самый доступный путь — protected, и вы не можете вызывать защищенные объекты вне иерархии наследования. - person Xeo; 22.01.2012
comment
@Xeo, Visual Studio говорит: не могу получить доступ к защищенному члену, тогда, если я поменяю список наследования, он скажет, что не может получить доступ к частному члену. как вы сказали, компилятор неправильно реализует эти правила :( - person codekiddy; 22.01.2012