这是关于“protected”的,其解释如下:“当一个类继承另一个类时,派生类的成员可以访问从基类继承的受保护成员。”但是,看看这段代码:
class Base {
public:
Base( int m ) : member(m){}
protected:
int member;
};
class Derived : public Base { // one of several subclasses
public:
Derived( int m ) : Base(m), value(10) {}
int diff( Base x ){
return value - x.member;
}
private:
int value;
};
派生访问“x.member”,它在Base类中受到保护,对吧?但编译器标记错误,“Base :: member is protected”。并且,在仔细研究了一下之后,我不得不同意编译器。
这就是问题:如何使这项工作最少,而且信息隐藏的损失最小?
我错过了什么吗?
答案 0 :(得分:3)
您可以保留受保护的属性,添加您提到的getter函数。对于受保护的指针属性,getter将确保返回int
(或大对象的const ref),并且您可以在函数模板中执行差异,然后获取Derived和Base参数(getters给出你计算的值。)
保护数据属性允许直接访问派生类中的受保护属性。您尝试的是访问另一个对象的私有属性。这部分代码:
int diff( Base x ){
return value - x.member;
}
等同于在main
中写这个:
Base x;
cout << x.member << endl;
以下是如何使用您自己建议的选项3解决问题的示例,其中派生类PointerDerived
使用指针存储:
#include <iostream>
class Base {
public:
Base( int m ) : member(m){}
int getMember() const
{
return member;
}
protected:
int member;
};
class Derived : public Base { // one of several subclasses
public:
Derived( int m ) : Base(m), value(10) {}
int getValue() const
{
std::cout << "protected = " << member << std::endl;
return value;
}
private:
int value;
};
class PointerDerived : public Base { // one of several subclasses
public:
PointerDerived( int m ) : Base(m), value(new int (10)) {}
int getValue() const
{
std::cout << "protected = " << member << std::endl;
return *value;
}
~PointerDerived()
{
delete value;
value = nullptr;
}
private:
int* value;
};
template<typename Derived, typename Base>
int diff(const Derived& d, const Base& b)
{
return d.getValue() - b.getMember();
}
using namespace std;
int main(int argc, const char *argv[])
{
PointerDerived p(23);
Base q(1);
cout << diff(p, q) << endl;
return 0;
}
由于nullptr,将程序编译为-std=c++11
,或将其更改为NULL
。
您使diff
成为一个函数模板,这样您就不必为每个派生类重载它,并让派生类处理存储并访问它,例如{ {1}}。
答案 1 :(得分:2)
您可以使用静态受保护的访问者:
class Base {
public:
Base( int m ) : member(m){}
private:
int member;
protected:
static int GetMember(const Base &b)
{ return b.member; }
};
class Derived : public Base { // one of several subclasses
public:
Derived( int m ) : Base(m), value(10) {}
int diff( Base &x ){ //beware of your slicing!
return value - GetMember(x);
}
private:
int value;
};
现在让我添加一下我为什么C ++访问控制以这种方式工作的想法...
C ++中的访问控制与信息隐藏无关。它是关于封装。也就是说,简单地说,如果使用不正确,您可以过滤掉任何可能破坏该类的成员的访问权。
理想的课程
如您所见,在我的计划中,受保护成员几乎没有地方:
受保护成员变量的位置更少。
因此,请将您的变量设为私有,并编写受保护的访问者。访问者必须是静态的才能从派生对象中使用。