【发布时间】:2014-07-29 03:42:04
【问题描述】:
我经常遇到想要实现数据结构的问题,并希望允许用户使用功能功能对其进行扩展;即向数据结构添加功能但不添加字节。一个例子可以是使用 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,但我发现这是不可接受的,原因如下:
- 如果两方已经使用方法扩展了类,其中一方想要使用,那么一方需要从一个子类转换为另一个子类。这是可笑的,因为将数据转换为数据而不实际更改字节,因为两个子类(可以)具有完全相同的内存实现和分段。另请注意,数据转换通常是样板代码,样板代码应被视为邪恶。
- 一个是不必要地将功能与数据结构混合在一起,例如,类名 sum_vector 或 mean_vector 完全是。
作为一个简短的提醒,我不是在寻找像“你不能在 c++ 中那样做”这样的答案,我已经知道了 (Add a method to existing C++ class in other file)。 不过,我想知道是否有一种很好的方法来进行功能类扩展。我应该如何管理访问私有字段?我想要私有字段访问是不合理的原因是什么?为什么我不能区分 extender 和 user 访问?
注意:可以说扩展器需要受保护的访问权限,而用户需要公共访问权限,但是,就像我说的,那将是扩展的继承方式,出于上述原因,我非常不喜欢它。
【问题讨论】:
-
必读:GotW #84
-
请不要!方法是一件很糟糕的事情。这些应该只是将结构作为第一个参数传递的语法糖。因为它们不是,你应该尽可能避免使用方法。
-
@polkovnikov.ph :我同意,我更喜欢函数而不是方法。但是,我是否应该通过将字段公开或添加公共访问方法来尽可能公开数据访问内容?
-
C# 改进的扩展方法,如果 C++ 委员会将来添加类似的东西,我会很高兴。
标签: c++ function class c++11 methods