2012-04-09 4 views
1

У меня есть объект класса Message, который можно записать и впоследствии обновить. Насколько я могу видеть, MessageUpdate IS-A MessageWrite:C++: Ограничить доступ метода в производном классе

class MessageWrite 
{ 
    protected: 
    void setVersion(int version_) {...} 
    void setReceiveTime(int tmReceive_) {...} 

    Message _msg; 
}; 


class MessageUpdate:public MessageWrite 
{ 
    //ONLY setVersionShould be accessible here, NOT setReceiveTime 
}; 

Есть ли сочетание уровня доступа метода и уровня наследования, которые могут помочь достичь этого?

Я знаю, что MessageUpdate можно просто сделать базовым классом, но есть rub: он приводит к шаблону алмаза в случае, если я хочу расширить класс сообщений. Рассмотрение:

class MessageUpdate {...}; 
class MessageWrite: public MessageUpdate {...}; 


//Now, while extending: 
class AdminMessageUpdate:public MessageUpdate {...}; 
class AdminMessageWrite: public AdminMessageUpdate, public MessageWrite //DIAMOND Pattern!! 

В чем разница в моем понимании наследства? И есть ли совершенно другой способ достичь этой логики без множественного наследования (как показано в последнем фрагменте кода)?

+0

Алмазный шаблон ОК до тех пор, пока вы не боитесь [виртуальное наследование] (http://en.wikipedia.org/wiki/Virtual_inheritance). – dasblinkenlight

+0

См. Http://stackoverflow.com/a/21607/13140 для примера использования виртуального базового класса, чтобы гарантировать, что вы не получите несколько копий «MessageWrite» в дереве наследования. Итак, вы хотите, чтобы ТОЛЬКО MessageWrite мог вызвать setReceiveTime()? –

+0

спасибо dasblinkenlight, но я бы предпочел использовать метод @Als, так как он экономит мне время выполнения нескольких наследований, а также – vid

ответ

1

Поскольку все члены MessageWrite являются protected, вы можете просто сделать setReceiveTime()private внутри MessageUpdate, поэтому классы, наследующие от MessageUpdate не смогут получить к нему доступ. Но у меня все еще есть некоторые проблемы с вашим дизайном, такие как:

Как вы думаете, что ваш дизайн позволяет избежать алмаза? не это в равной степени привело бы к:

class MessageWrite {...}; 
class MessageUpdate: public MessageWrite {...}; 

//Now, while extending: 
class AdminMessageWrite:public MessageWrite {...}; 
class AdminMessageUpdate: public AdminMessageWrite, public MessageUpdate //DIAMOND Pattern!! 

Почему вы думаете MessageUpdate IS-A MessageWrite, когда вы позже сказать, что это не является (указав, что не все MessageWrite относится к ней)? Если этот код не должен быть действительным:

MessageWrite& m = MessageUpdate(); 
m.setReceiveTime(); // Should this be valid? 

затем MessageUpdate IS-НЕ-A MessageWrite. Если мой код должен быть действительным, тогда нет причин, позволяющих избежать доступа к setReceiveTime() в MessageUpdate.

И вы, вероятно, будет лучше, создав базовый класс AdminMessage, а затем наследовать непосредственно от него, чтобы избежать алмаз:

class MessageWrite {...}; 
class MessageUpdate: public MessageWrite {...}; 

//Now, while extending: 
class AdminMessage {...}; 
class AdminMessageWrite: public MessageWrite, public AdminMessage {...}; 
class AdminMessageUpdate: public MessageUpdate, public AdminMessage {...}; // No diamond 
0

protected: унаследованные пользователи могут получить доступ.

частный: унаследованные пользователи не могут получить доступ.

protected: 
    void setVersion(int version_) {...} 
    private: 
    void setReceiveTime(int tmReceive_) {...} 
2

Просто объявить метод:

private: 
void setReceiveTime(int tmReceive_); 

private с спецификатора доступа в базовом классе MessageWrite.

Это мой ответ должен быть хорошо читать:

What are access specifiers? Should I inherit with private, protected or public?

+0

спасибо, thats spot on. Я не могу сделать это автоматически? Необходимо переписать все объявления методов? – vid

+0

@vid: Вам нужно будет сделать это вручную. Кроме того, спецификаторы доступа для членов класса указаны в определении класса для объявлений методов. Обратите внимание, что обычно методы класса * объявляются * в файле заголовка и * определены * в файле cpp. –

1

Если MessageUpdate есть-MessageWrite, то по определению, он имеет доступ ко всем его защищенных и открытых членов.

Так что, если есть члены, которые вы хотите публично/protectedly подвергавшихся воздействию в MessageWrite, что вы не хотите подвергаться в MessageUpdate, то по Liskov Substitution Principle, MessageUpdate не может быть MessageWrite.

+0

+1 для принципа – vid

Смежные вопросы