我觉得这个问题之前肯定有人问过,但我在谷歌上四处寻找却找不到答案。如果有请给我一个链接,我会删除这篇文章。
考虑这个代表我遇到的更大问题的最小示例。假设我像这样创建了一个简单的“Point”和“Printer”类:
class Point {
public:
double x, y;
Point() {x = y = 0;}
Point(double x, double y) {
this->x = x; this->y = y;
}
};
template<typename T>
class Printer {
public:
T* mData;
int mSize;
// Constructor
Printer(std::vector<T> &input) {
mData = &input[0];
mSize = input.size();
}
// Simple Print function
void Print() {
printf(" - Showing %d items\n", mSize);
for (int i = 0; i < mSize; i++) {
const T &item = mData[i];
printf(" - Item %d: (%lf, %lf)\n", i, item.x, item.y);
}
}
};
我可以像这样使用打印机类:
std::vector<Point> points; // fill the vector, and then...
Printer<Point> pointsPrinter(points); pointsPrinter.Print();
现在假设其他人出现并希望使用 Printer 类,其中声明了自己的“Point”类,如下所示:
class Pnt {
public:
double mX, mY;
// other stuff
};
如果他们尝试这样做:
vector<Pnt> pnts; // Fill the pnts, and then...
Printer<Pnt> pntsPrinter(pnts);
pntsPrinter.Print(); // COMPILE ERROR HERE!
显然这会失败,因为 Pnt 没有 x 或 y 成员。是否存在一种方法可以重写 Printer 类以适用于所有通用用户类型?我不想做的是将 Pnt vector 复制到点 vector 中。
编辑:
我能想到的唯一方法是传递函数指针。像这样:
template<typename T>
class Printer {
public:
T* mData;
int mSize;
double* (*mXFunc) (T*);
double* (*mYFunc) (T*);
Printer(std::vector<T> &input,
double* (*xFunc) (T*),
double* (*yFunc) (T*))
{
mData = &input[0];
mSize = input.size();
mXFunc = xFunc;
mYFunc = yFunc;
}
void Print() {
printf(" - Showing %d items\n", mSize);
for (int i = 0; i < mSize; i++) {
T &item = mData[i];
printf(" - Item %d: (%lf, %lf)\n", i, *mXFunc(&item), *mYFunc(&item));
}
}
};
// Could then use it like so
inline double* getXPointVal(Point *point) {return &point->x;}
inline double* getYPointVal(Point *point) {return &point->y;}
inline double* getXPntVal(Pnt *point) {return &point->mX;}
inline double* getYPntVal(Pnt *point) {return &point->mY;}
Printer<Pnt> pntPrinter(pnts, getXPntVal, getYPntVal);
Printer<Point> pointsPrinter(points, getXPointVal, getYPointVal);
pntPrinter.Print();
pointsPrinter.Print();
问题是它看起来很丑,而且还可能引入函数调用开销。但我想函数调用开销会被编译掉吗?我希望存在更优雅的解决方案...
最佳答案
如果选择cout
而不是 printf
要编写输出,您可以允许所有可打印类型为 <<
定义重载运算符并在 Printer::print()
中一般使用它.重载可能如下所示:
std::ostream& operator<<(std::ostream &out, Point& p){
out << "Point(" << p.x << ", " << p.y << ")";
return out;
}
附带说明一下,我建议不要存储指向 vector
的指针。的内部存储和大小成员。如果 vector 需要重新分配,您的指针将悬空且无效。相反,您应该暂时将 vector 作为引用传递或保留常量引用。
关于c++ - 使 C++ 类与通用用户定义的输入一起工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38466578/