Если вы хотите, чтобы ваш код с базовыми классами имел независимую функциональность и при этом оставался защищенным, самый простой способ решить вашу проблему - слегка изменить имя защищенных функций и добавить открытую функцию, которая вызывает защищенные члены:Посмотрите эти объявления класса, например:
class A {
public:
void func( int& a ) {
func_impl( a );
}
protected:
void func_impl( int& a ) {
a = a * 2;
}
};
class B {
public:
void func( int& b ) {
func_impl( b );
}
protected:
void func_impl( int& b ) {
b = b * 3;
}
};
class C {
public:
void func( int& c ) {
func_impl( c );
}
protected:
void func_impl( int& c ) {
c = c * 5;
}
};
class D : public A, public B, public C {
public:
int a;
A a_val;
B b_val;
C c_val;
void update_val( int val ) {
a = val;
a_val.func( a );
b_val.func( a );
c_val.func( a );
}
void check( int );
};
void D::check( int val ) {
update_val( val );
std::cout << "Value = " << a << std::endl;
}
Это обеспечивает хороший публичный интерфейс для вызова защищенных функций-членов.Это также решает проблему доступа к protected members
.Когда я запускаю вашу программу и ввожу значение 5
, она возвращает результат 150
и работает как положено.
Этот фрагмент должен показать вам, как работает наследование, когда вы можете и не можетеДоступ к защищенным членам:
class DerivedA : public Base {
public:
Base b;
void call_message() {
b.message(); // Protected Member of Base class can not be accessed
}
};
class DerivedB : public Base {
public:
void call_message() {
message(); // This works without problem!
}
};
Точно так же, как я делал выше, один из способов решения этой проблемы - добавление вызывающей стороны открытого интерфейса к защищенной реализации.
class Base {
public:
void message() {
message_impl();
}
protected:
void message_impl() {
std::cout << "This is a protected member of Base\n";
}
};
Теперь вы можете сделать это:
class DerivedA {
public:
Base b;
void call_message() {
b.message(); // Accessible through public interface.
}
};