C++ 调用具有不同签名的函数,具体取决于类型

C++ Calling functions with different signatures, depending on type

我想知道以下场景的良好设计模式是什么。三问:

1) 我有一个模板 "Container" class 用于 "Derived" 的子class。我希望能够在一个向量中存储不同种类的模板对象(类型 A 或 B,都是 Derived 的 subclasses)。如何做到这一点?

2) 我有一个特定于模板的函数 "func",它在 Container 上运行并且具有可变数量的参数,具体取决于 Container 的模板类型是 A 还是 B。检查的好方法是什么模板类型在运行时调用适当的函数?

3) 模板对这个用例有意义吗?

#include <iostream>
#include <string>
#include <vector>
#include <memory>

using namespace std;

struct Derived {};

struct A : Derived { 
    int x; 
    A(int x) : x(x) {}
};
struct B : Derived { 
    bool y; 
    B(bool y) : y(y) {}
};

template <typename T>
struct Container
{
    T item;
    Container(T i) : item(i) {}
};

// definition of a template function for type a, with specialization
void func(Container<A> c, int a, int b) {
    cout << "update for A called" << endl;
}

void func(Container<B> c, bool x) {
    cout << "update for B called" << endl;
}

int main(int argc, char const *argv[])
{
    Container<A> * foo = new Container<A>(A(1));
    Container<B> * bar = new Container<B>(B(true));
    // test that func() works
    func(*foo,1,2);
    func(*bar,false);

    vector< Container<Derived>* > vec;

    // this does not work
    vec.push_back(unique_ptr< Container<Derived *> >(foo));
    vec.push_back(unique_ptr< Container<Derived *> >(bar));

    for (Container<Derived>* d : vec) {
        // how to call the proper func(d)?
    }
    return 0;
}

1) 您可以将指向 A 的指针(类型 A *)或指向 B 的指针(类型 B *)存储在 std::vector<Derived *> 中,因为DerivedAB 的基础。不能把一个Container<A>和一个Container<B>存到同一个vector中,因为它们之间没有继承关系。这也是(间接)将 foobar 转换为 unique_ptr<Container<Derived *> > 被编译器拒绝的原因。

2) 你的 func() 不是 "template specific function"。它甚至不是模板函数。它是一个重载函数,一种变体接受两个参数,另一种变体接受三个参数。

3) 鉴于您的代码无效,无法推断您的用例是什么。鉴于您正在尝试将对象转换为不相关的类型,我的猜测是您的用例在 C++ 中没有意义,更不用说为其使用模板了。

此外,不要在 C++ 中使用 Java(或您正在考虑的任何其他语言)技术,因为它们的工作方式不同。具体来说;

Container<A> * foo = new Container<A>(A(1));
Container<B> * bar = new Container<B>(B(true));
func(*foo,1,2);
func(*bar,false);

不需要。由于各种原因在 Java 中使用它在 C++ 中无效,即使代码可以编译。相反,这样做;

Container<A> foo A(1);
Container<B> bar B(true);
func(foo,1,2);
func(bar,false);

这是有效且安全的 C++(在 Java 中不起作用,但那是另一回事了)。