C ++ / Алмазное наследование / Статические переменные - PullRequest
0 голосов
/ 05 марта 2011

У меня возникли некоторые проблемы с дизайном, я хотел бы написать:

class A { ... };
class B : public A { static string type_; ... };
class C : public A { static string type_; ... };
class D : public B, public C { static string type_; ... };

Я думаю, что до определения класса C у меня не возникнет проблем ... но что произойдет, когда я определю класс D? Поскольку D будет наследовать от B и C, у меня, вероятно, будет что-то неоднозначное. Моей конечной целью было бы иметь в каждом классе B, C и D статическую переменную, которая имела бы то же имя, но другое значение. Это возможно?

Большое спасибо заранее Sed

Ответы [ 4 ]

3 голосов
/ 05 марта 2011

Код у вас здесь отлично.Классам разрешается определять членов с любыми именами, которые они хотят, даже если они соответствуют имени члена в родительском классе.Единственный раз, когда у вас возникнут проблемы, это если с использованием , то одно из этих имен приведет к двусмысленности.

В вашем случае наличие трех static членов данных в классах B, C и D не вызовут никаких проблем, и экземпляр каждого класса type_ будет отличаться от всех остальных.То, что они имеют одинаковое имя, не означает, что C ++ рассматривает их как переопределения;только virtual функции-члены могут быть переопределены.

В контексте каждого класса и его функций-членов любые ссылки на name_ всегда будут ссылаться на name_ из этого класса, так как классы скрывают имена отлюбой из их базовых классов и поэтому компилятор будет смотреть только в текущем классе.В глобальном масштабе вы можете ссылаться на поля name_ с их полностью определенными именами, например A::name_, B::name_ и т. Д.

Что более важно, тип наследования, который вы здесь используете, виртуальный или не-virtual, не имеет значения, потому что здесь обсуждаются только имена переменных.Поскольку существует только одна копия каждого элемента данных static, то, закончит ли ваш класс D наследование двух копий A::name_, не имеет значения; не может наследовать две копии, поскольку существует только одна.

0 голосов
/ 05 марта 2011

Если вы напишите type_ в методе в D, он будет преобразован в D s type_. Если вы напишите A::name_ или B::name_, он будет преобразован в type_.

соответствующего экземпляра.

С другой стороны, кажется, что вы пытаетесь взломать какую-то систему отражения на C ++, поскольку у вас есть статические поля с именем type_ в каждом классе. Это может быть полезно в некоторых редких случаях, но, вероятно, это плохая идея.

0 голосов
/ 05 марта 2011

В алмазном наследовании есть одно решение, предусмотренное стандартом C ++, чтобы избежать чего-то неоднозначного.

Ваша структура определения класса выглядит примерно так:

                       A
                      /  \
                     /    \
                    /      \
                   B        C
                    \      /
                     \    /
                      \  /
                       D 

Теперь, когда вы наследуете класс A в классеB использует следующее

class B : public virtual A

То же самое для класса C.

Так что, когда любой класс наследует от класса B & C, тогда у него будет только один экземпляр класса A.

Нет необходимости виртуального наследования для класса D. Это не имеет никакого эффекта.

Размер класса D может быть таким же, как и раньше, но любой адрес доступа к переменной из класса B и класса C будет таким же, когда вы создаете экземплярD.

0 голосов
/ 05 марта 2011

Там нет ничего двусмысленного вообще. Вы сможете ссылаться на оба поля как B::type_ и C::type_.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...