c++ - 使 C++ 类与通用用户定义的输入一起工作

标签 c++ linux templates

我觉得这个问题之前肯定有人问过,但我在谷歌上四处寻找却找不到答案。如果有请给我一个链接,我会删除这篇文章。

考虑这个代表我遇到的更大问题的最小示例。假设我像这样创建了一个简单的“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/

相关文章:

c++ - 我如何告诉编译器不要创建临时对象?

Linux Socket::connect 和 QT::connect 混合

c++ - 如何使用friend访问STL私有(private)成员

c++ - 具有类型模板参数默认值的非类型模板参数

c++ - 如何在 OSX Mavericks 中为 Xcode 5.0.2 安装命令行工具?

c++ - 在不更改输入的情况下确定字符串是否为回文

c++ - 函数模板重载 - 特化

c - 是否有可能在c中同时运行主线程及其子线程

linux - Linux下无法安装bower

mongodb - 对如何调用模板渲染操作感到困惑