我们如何改变C++的行为方法取决于初始化参数?

发布于 2025-01-23 03:26:55 字数 784 浏览 1 评论 0原文

在Python中,我可以写一些类似的内容

class C:
    def __init__(self, mode):
        if mode == 0:
            self.f = self.f0
        elif mode == 1:
            self.f = self.f2
        (...)
        else:
            raise KeyError

    def f0(self, a1, a2):
        <do stuff>

    def f1(self, a1, a2):
        <do other stuff>

    (...)

,可以替代用子类c1c2,...覆盖f。简短的问题是:我可以在C ++中做类似的事情而不召唤Cthulhu吗?

在任何人问“为什么”之前:

这很有用,例如,如果我有另一个类d,则使用c,因为它允许参数mode简单地将其传递到c而不是在任何地方撰写c的实例的单独情况。

我想避免switch如果 -tree每次都会f被称为,因为f是在本来已经昂贵的计算中多次称为 的小功能。

In python I can write something like

class C:
    def __init__(self, mode):
        if mode == 0:
            self.f = self.f0
        elif mode == 1:
            self.f = self.f2
        (...)
        else:
            raise KeyError

    def f0(self, a1, a2):
        <do stuff>

    def f1(self, a1, a2):
        <do other stuff>

    (...)

As an alternative to writing a parent class with subclasses C1, C2, ... that overwrite f. The short question is: Can i do something similar in C++ without summoning Cthulhu?

Before anyone asks "why":

This is useful, for example if I have another class D, that uses C, because it allows the parameter mode to simply be passed on to C rather than writing separate cases everywhere an instance of C is initialised.

I want to avoid a switch or if-tree that is evaluated every time f is called, because f is a small function that is called very many times in an already expensive calculation.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

半仙 2025-01-30 03:26:56

感谢@alanbirtles和@yksisarvinen!

我最终得到的工作解决方案是

stuff.h

class C{

    C(int mode);

    const int mode;
    double f(int i, int j, int k);

    using FunctionType = double(C::*)(int, int, int);
    double f0(int i, int j, int k);
    double f1(int i, int j, int k);
    FunctionType f_p;
};

stuff.cpp

C::C(int mode) : mode{mode} {
    switch (mode){
    case 0:
        f_p = &C::f0;
        break;
    case 1:
        f_p = &C::f1;
        break;
    default: throw "Non-valid mode!";
    }
}
double C::f(int i, int j, int k) {std::invoke(f_p, this, i, j, k);}
double C::f0(int i, int j, int k){ <do stuff> }
double C::f1(int i, int j, int k){ <do other stuff>}

正如@MCH所建议的那样,使用模板类可能同样简单。但是(问题未指定)我需要使用pybind11与Python-wrapper一起使用,因此上述解决方案允许我避免与包装模板类有关的任何麻烦。

Thanks to @AlanBirtles and @Yksisarvinen !

The working solution I ended up with was

stuff.h:

class C{

    C(int mode);

    const int mode;
    double f(int i, int j, int k);

    using FunctionType = double(C::*)(int, int, int);
    double f0(int i, int j, int k);
    double f1(int i, int j, int k);
    FunctionType f_p;
};

stuff.cpp:

C::C(int mode) : mode{mode} {
    switch (mode){
    case 0:
        f_p = &C::f0;
        break;
    case 1:
        f_p = &C::f1;
        break;
    default: throw "Non-valid mode!";
    }
}
double C::f(int i, int j, int k) {std::invoke(f_p, this, i, j, k);}
double C::f0(int i, int j, int k){ <do stuff> }
double C::f1(int i, int j, int k){ <do other stuff>}

As suggested by @mch, using a template class would probably have been just as simple. However (not specified in the question) I needed this to work with a python-wrapper using pybind11, so the above solution allowed me to avoid any trouble related to wrapping a template class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文