这个问题已经被提出here - 实际上已经超过两次了 - 但是我自己也无法从帖子中找到解决问题的方法。
我拥有的是一个库,其中包含一个名为A
的类。从课程A
我需要访问std::map<>
,但它是私有的。另外,基于我在上面提到的帖子中找到的可能性,类A
具有没有模板化函数。
我实际上能够重新编译库,这样我就可以简单地改变可见性。 然而,这将是很多的工作 - 而且我不确定更改可见性是否会导致其他任何事情崩溃。
我想要做的是,在课程B
中:
// NOT MY CODE -- library <a.h>
class A {
private:
std::map<int, int> A_map;
};
// MY CODE -- module "b.h"
# include <a.h>
class B : private A {
public:
B() {
for (auto it(A_map.begin()); it != A_map.end(); ++it) {
...;
}
}
};
如果不更改原始类,如何在基类中没有任何可用的模板化方法来重载/专用?
答案 0 :(得分:3)
你应该首先非常确信你想要做的事实际上是有效的......可能有一个很好的理由,即变量是私有的。修改它可能会破坏A实例的状态,并且当您打破封装以读取它时,无法保证私有变量将处于逻辑或一致状态。
有了这个警告,如果你可以修改/重新编译声明你的类的库,那么A的朋友可能就是这样。让B通过合成持有A的实例,因为它是朋友,所以它可以访问A实例的私有成员。
而且,因为我感觉特别邪恶,这是一个如何在不修改A的情况下打破封装的演示。虽然它不可移植(我在64位Linux上用g ++工作)并且需要弄清楚内存中对象布局。为简单起见,我将地图更改为矢量。
#include<vector>
#include<iostream>
class A {
private:
int blah; //Just to make it a bit more realistic.
std::vector<int> A_vec;
public:
void outputVec() {
std::vector<int>::iterator it = A_vec.begin();
while(it != A_vec.end()) {
std::cout << *it << std::endl;
++it;
}
}
};
int main() {
A* a = new A();
std::vector<int>* v = (std::vector<int>*)(((char*)a)+sizeof(long));
v->push_back(27);
v->push_back(12);
a->outputVec();
return 0;
}
答案 1 :(得分:2)
故意保护私有变量免受任何外部访问。如果拥有的类通过限制较少的访问权限或结交朋友,您只能访问成员。
并且我不确定更改可见性是否会导致其他任何事情崩溃。
C ++中的访问限制是故意设计的,因此在进行名称查找时,可访问性是最后检查的内容。这意味着如果你有一个工作程序并且你做了一些更容易访问的东西,那么程序的行为根本不应该改变,因为在检查可访问性之前已经检查了所有其他潜在的问题。
答案 2 :(得分:1)
首先,将所有数据成员保密是一个非常好的主意。如果派生类确实需要访问A_map
,那么最好的做法是给基类一个getter,它返回一个const引用(假设你只需要read-access)。如果您需要A_map
的写入权限,那么这表明您需要重新考虑您的设计。
除此之外,如果不严重违反C ++的规则和惯例,就无法授予B
A_map
类A
的访问权。
顺便说一句,私有继承意味着别的东西。这意味着类B
的所有公共方法都将成为类A
的私有方法。换句话说,私有继承意味着您继承了{{1}}的实现,而不是它的接口。所以这对你没用。
答案 3 :(得分:0)
私人继承实际上是伪装的组合!它实际上意味着“以”实施“。
将它放在一边,不管私有/公共/受保护的继承模式如何,私有成员将保持私有(在该类之外无法访问,即使是派生的也是如此)。
有两种合法方式可以访问任何类的私有成员。
1)使用Get / Set方法访问私有成员(假设类暴露它)。
2)与全班同学。
在您的情况下,A类属于库,库供应商有责任为外部世界提供与A类交互的适当接口。或许,最好与库供应商进行交流。对我来说,它看起来更像是一个设计问题,而不是实现问题。
仅仅为了测试,作为一个快速黑客,我建议建立友好机制。
class A {
friend class B;
private:
std::map<int, int> A_map;
};
// MY CODE -- module "b.h"
class B {
public:
B() {
for (std::map<int, int>::iterator it(a.A_map.begin());
it != a.A_map.end(); ++it) { }
}
A a;
};