C++ 当受到保护时,保护太多
这是关于“protected”的,解释为:“当一个类继承另一个类时,派生类的成员可以访问从基类继承的受保护成员。”但是,请看以下代码:C++ 当受到保护时,保护太多,c++,inheritance,protected,C++,Inheritance,Protected,这是关于“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
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::member受保护”。在仔细考虑了一分钟后,我不得不同意编译器的观点
问题来了:我该如何在信息隐藏损失最小的情况下实现这一点
我遗漏了什么吗?您可以保留受保护的属性,添加您提到的getter函数。对于受保护的指针属性,getter将确保返回
int
(或大型对象的const ref),并且您可以在函数模板中执行不同操作,该模板采用派生参数和基参数(getter为您提供计算值)
保护数据属性允许直接访问派生类中的受保护属性。您尝试的是访问另一个对象的私有属性。这部分代码:
int diff( Base x ){
return value - x.member;
}
这相当于在main
中写入:
Base x;
cout << x.member << endl;
由于NULL PTR,请使用-std=c++11
编译程序,或将其更改为NULL
您将
diff
作为函数模板,这样您就不必为每个派生类重载它,并且您可以让派生类处理存储和对它的访问,例如PointerDerived
您可以使用静态保护访问器:
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++访问控制这样工作……/P> < C++中的访问控制不是信息隐藏。它是关于封装的。也就是说,简单地说,您过滤掉了对任何成员的访问,如果使用不当,这些成员可能会破坏类
在理想的班级里- 公共成员不能用于断开对象
- 私人成员知道他们在做什么
- 受保护的成员用于实现继承接口(如果有)
因此,将变量设为私有,并编写一个受保护的访问器。访问器必须是静态的,才能从派生对象使用。只需定义
int diff(派生x)
,还是不定义?阅读第1点和第3点时,可以得出结论,保护成员感知是可以读取,但不能更改。因此,get方法可以很好地实现这一点。此外,还可以使用一个公共常量引用或指向const to member的const指针,该引用或指针在Base的构造函数列表中初始化。您的第3点和“您能做的最好的…const X*”取决于您想要什么:get方法无论如何都会返回值。因此,无法使用X*get()
更改类型为X*的成员的值。只有它所指向的。如何制作一个函数int diff(派生的d,基b)
,并将此函数作为两个类的朋友?@mb84 diff-type-Base,以便使其对所有可能的子类型都有用。(可能Base*会让意图更清楚,但我不是在追求多态性。)-我最初的情况是成员的类型为char*,我不喜欢返回这个指针,即使是const char*@rozina OK,如果没有太多地方需要这种访问的话。这段代码中的一些代码回答了一个没有被问到的问题。我真的不确定这对OP也有帮助,更不用说其他试图找到原始问题答案的人了。我只是添加了int*,因为OP要求将X*作为受保护的数据成员。之所以会有获得者,是因为OP说对于一个简单的例子来说,这是可以接受的。diff是一个函数,因为getter确保PointerDerived返回一个int-对于这个简单的示例。这有意义吗?“变量没有定义正确的接口”:对于std::pair
;-)来说是个坏消息当然,它不是用来作为基类的,所以我真正要争论的是你是否应该说“变量没有定义一个合适的继承接口”或者诸如此类的话。@SteveJessop:hmm,爸爸,用词的选择。当然,它们可以是接口的一部分。我的意思是,由变量组成的接口是无限的,所以不能对它们强制使用不变量。如果这是你想要的,那就公开;如果没有,就私下进行;但是受保护的变量没有什么意义。当然,在某些情况下,它们可能有用(我已经使用过),但并不多。同意,pair
是特殊的,因为根据定义,它的两个成员是独立的。没有类不变量将它们联系起来。@rodrigo“人们可能认为信息隐藏是原理,封装是技术”,正如维基百科所说,我倾向于同意作者的观点。最终意味着同样的事情我也不喜欢受保护,尽量少用。-我喜欢静态getter的想法,尽管,嗯,。。。
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;
};