我经常遇到我想要实现数据结构的问题,并希望允许用户使用功能扩展它;这是向数据结构添加功能但不添加字节。一个例子可以是使用sum方法扩展std :: vector:
#include <iostream>
#include <vector>
// for the header file
template<>
int std::vector<int>::sum();
//for the object file
template<>
int std::vector<int>::sum() {
int s=0;
for(auto v = this->begin(); v!=this->end(); ++v) s+=*v;
return s;
}
int main() {
std::vector<int> numbers;
numbers.push_back(5);
numbers.push_back(2);
numbers.push_back(6);
numbers.push_back(9);
std::cout << numbers.sum() << std::endl;
return 0;
}
所以这是非法的,因为有人可能不会向这样的类添加函数。显然这是c ++(11)的一些设计决定。它可以通过两种方式规避,即定义
int sum(std::vector<int> &v) { ... }
这就是std :: sort的工作原理,所以我猜这是c ++(11)的用途。我认为这是我所知道的最好的c ++方法。但是,它不允许我访问std :: vector的私有属性。也许我是邪恶的假设访问(排序)方法中的私有属性是公平的。但是,我经常希望我的类的用户不能访问某些东西,但是我希望允许我的扩展程序访问它们。例如,我可以想象std :: sort可以优化w.r.t.具体的容器实施知识和访问。
另一种方法是继承std :: vector,但由于以下原因,我觉得这是不可接受的:
作为一个简短的提醒,我不是在寻找像“你不能用c ++这样做”的答案,我已经知道了(Add a method to existing C++ class in other file)。 但是,我想知道是否有一种很好的方法来执行功能类扩展。我该如何管理访问私有字段?什么原因导致我想要私人现场访问是不合理的;为什么我不能区分扩展程序和用户访问权限?
注意:可以说扩展器需要受保护的访问权限而用户需要公共访问权限,但是,就像我说的那样,这将是继承的扩展方式,并且由于上述原因我强烈反对。
答案 0 :(得分:2)
您永远不应该访问标准容器的私有成员,因为它们不是其接口的一部分。
但是,您已经可以扩展标准容器的功能,如std::vector
:即通过明智地使用迭代器和标准算法。
E.g。 sum
功能由使用begin()
的{{1}}和end()
功能的非成员函数提供
std::vector
答案 1 :(得分:0)
考虑这样的事情:
#include <iostream>
class Foo{
int a;
public:
Foo(int a){this->a = a;}
int getA(){return this->a;}
void * extendedMethod(void *(*func)(int, char **, Foo*), int argc, char **argv){
return func(argc, argv, this);
}
};
void * extendFooWith(int argc, char **argv, Foo* self){
/* You can call methods on self... but still no access to private fields */
std::cout << self->getA();
return self;
}
int main(int argc, char const *argv[])
{
Foo foo(5);
foo.extendedMethod(extendFooWith, 0 /*argc*/, NULL /*argv*/);
return 0;
}
这是我想用方法扩展类的最好方法。访问私有字段的唯一方法是从extendedMethod()
内部开始,即这样的事情是可能的:return func(this->a, argv, this);
但是它不再是那种通用的。改进它的一种方法是检查内部extendedMethod()
传递了什么类型的指针,并根据它访问您感兴趣的私有字段并将其传递给func()
,但这需要添加代码{ {1}}对于所有其他方法,您将使用。