c++ - 如何导出模板函数?或者这种情况的首选方法是什么?

标签 c++ templates virtual

我有两个功能

MultiplyVerison1(T x, T y); // in class A
MultiplyVersion1(T x, T y); // in class B

以上函数位于单独的非模板类中。

现在,作为重构的一部分,我尝试创建 AB 的基类,并创建一个 纯虚拟 MultiplyVersion1 但是模板函数不能被标记为虚拟。

那么,我们怎样才能用模板函数实现同样的效果呢?

最佳答案

你不能。无法通过基类指针调用派生类中的函数模板,这就是“函数模板不能是虚拟的”的意思。

您可以认为这是因为它是触发具有特定类型 T 的函数模板实例化的调用。 -- 如果你用 int 来调用它,但是您调用它的对象的动态类型直到运行时才知道(无论是 A 还是 B 还是其他类型),那么编译器就无法知道它需要实例化 A::MultiplyVersion1<int>B::MultiplyVersion1<int>或者是其他东西。实际上还有更多,但我认为这就足够了。

您可以回避特定情况,但无法获得虚函数的全部效果。像这样的东西:

struct Base {
    template <typename T>
    void MultiplyVersion1(const T &x, const T &y) {
        A *athis = dynamic_cast<A*>(this);
        if (athis) {
            athis->MultiplyVersion1(x,y);
        } else {
            B *bthis = dynamic_cast<B*>(this);
            if (bthis) {
                bthis->MultiplyVersion1(x,y);
            } else {
                throw std::logic_error();
            }
        }
    }
    virtual ~Base() {}
};

现在当你调用MultiplyVersion1<int>时通过指向基址的指针, A::MultiplyVersion1<int>B::MutiplyVersion1<int>被实例化。但当然你不能轻易地添加新的派生类,这是一个严重的限制。

您还可以重新考虑是否真的需要动态多态性,但这完全取决于您计划如何使用该基类。到目前为止,没有它你似乎也做得很好。

如果您想要从基类中得到的只是代码重用于某些其他函数,那么您不需要动态多态性。离开MultiplyVersion1完全脱离基类(也许不要从 Base 公开继承,而是私有(private)继承并引入您想要通过 using 语句重用的函数)。如果您想定义重复使用的函数,请调用 MultiplyVersion1 ,然后考虑通过 CRTP 模拟动态绑定(bind):

#include <iostream>

template <typename Derived>
struct Base {
    template <typename T>
    void MultiplyVersion2(const T &x, const T &y) {
        static_cast<Derived&>(*this).MultiplyVersion1(x + 1, y + 1);
    }
};

struct A : private Base<A> {
    friend class Base;
    template <typename T> void MultiplyVersion1(T x, T y) {
        std::cout << x*y << "\n"; 
    }
    using Base::MultiplyVersion2;
};

struct B : private Base<B> {
    friend class Base;
    template <typename T> void MultiplyVersion1(T x, T y) {
        std::cout << x << " * " << y << " = " << x*y << "\n"; 
    }
    using Base::MultiplyVersion2;
};

int main() {
    A a;
    a.MultiplyVersion2(1,2);
    B b;
    b.MultiplyVersion2(1,2);
}

关于c++ - 如何导出模板函数?或者这种情况的首选方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9033189/

相关文章:

具有友元函数和运算符重载的 C++ 模板

javascript - 如何从模板节点复制并填充 json 数据并使用 javascript 将它们附加到文档中?

c# - 将方法/属性标记为虚拟的性能影响是什么?

image - 无法使用 PowerShell 捕获的镜像创建新的 AzureVM

c++ - 在 C++ 中设计 ABC(抽象基类)的良好实践

c++ - 无法使用 istream 和 ostream 指针跨 Linux 管道写入

c++ - 模板模板参数什么时候成为标准的一部分?

c++ - Virtual 关键字使派生对象中的方法不可访问

c++ - 视频中的多重跟踪

c++ - Win7下eclipse未启用SSE指令集