Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我如何编写一个函数,用同一个接口接受不同类型的参数?_C++_Function_Interface_Arguments - Fatal编程技术网

C++ 我如何编写一个函数,用同一个接口接受不同类型的参数?

C++ 我如何编写一个函数,用同一个接口接受不同类型的参数?,c++,function,interface,arguments,C++,Function,Interface,Arguments,考虑这个简化的例子: #include <list> typedef std::list<int> IntList; class KindaIntList { public: IntList::const_iterator begin() const { /* do some stuff */ } IntList::const_iterator end() const { /* do some stuff */ }

考虑这个简化的例子:

#include <list>

typedef std::list<int> IntList;

class KindaIntList {
    public:
        IntList::const_iterator begin() const { /* do some stuff */ }
        IntList::const_iterator end() const { /* do some stuff */ }
        // ...etc
};
它只调用由
KindaIntList
实现的方法。我希望能够使用
IntList
KindaIntList
参数调用它。可能吗


我考虑过使用模板,但是
f
的定义非常大,我不想把它放在头文件中(
f
是一个类的成员,我不想让它内联)

编辑


函数
f
实际上是另一个类的
virtual
成员;因此,我不知道如何将其变成模板成员。

您可以重载
f
以获取
IntList
KindaIntList
,如下所示:

void f(IntList l){...}
void f(KindaIntList l){...}
class MyClass {
public:
    virtual void f(ListWrapper list) {
        list.push_back(137); // For example
    }
};
或者使用迭代器:

void f(IntList::iterator first, IntList::iterator last){...}
也就是说,对于这两种情况,模板确实是最佳选择:

template<class ListT>
void f(ListT l){...}
template<class Iter>
void f(Iter first, Iter last){...}
模板
空f(列表l){…}
模板
无效f(Iter第一,Iter最后){…}

您可以重载
f
来获取
IntList
KindaIntList
,如下所示:

void f(IntList l){...}
void f(KindaIntList l){...}
class MyClass {
public:
    virtual void f(ListWrapper list) {
        list.push_back(137); // For example
    }
};
或者使用迭代器:

void f(IntList::iterator first, IntList::iterator last){...}
也就是说,对于这两种情况,模板确实是最佳选择:

template<class ListT>
void f(ListT l){...}
template<class Iter>
void f(Iter first, Iter last){...}
模板
空f(列表l){…}
模板
无效f(Iter第一,Iter最后){…}

> p>尽管您对模板感到疑虑,但这确实是使用C++模板的合适位置。模板函数完美地捕捉了“此函数可用于任何参数,只要我对这些参数执行的操作定义良好。”

在这种情况下,您不需要担心内联。除非在类的主体内部定义
f
,否则它不会自动内联,即使它是一个模板。例如,在此代码中:

class MyClass {
public:
     template <typename T> void f(T&);
};

template <typename T> void MyClass::f(T&) {
    /* ... implementation ... */
}
或者,您可以为模板实现创建一个单独的
.h
文件,然后在头文件的底部包含该文件。这会使客户机看不到模板实现,除非他们主动去寻找它

希望这有帮助

EDIT:如果
f
是虚拟的,那么您就不能将其作为模板函数(您可能已经知道)。因此,如果您想让它适用于“碰巧看起来像
std::list
”的事情,那么您没有很多好的选择。通常,您会为
std::list
和自定义列表类型创建一个基类,但这不是一个选项,因为您不能修改
std::list

幸运的是,有一种方法可以使用称为外部多态性的技巧以多态性的方式处理
std::list
和类似的事物。其思想是,虽然您无法使适当的类以多态方式运行,但可以通过引入多态类层次结构,在这些对象周围添加额外的间接层,该层次结构只将其所有请求转发给本身不具有多态性的对象

如果您愿意使用大型模板枪,那么可以将此逻辑封装在一个类中,该类的工作方式与新的
std::function
模板类型基本相同。想法如下。首先,我们将创建一个多态基类,将所有要调用的函数导出为纯虚拟函数:

class List {
public:
    virtual ~List() {}

    virtual std::list<int>::const_iterator begin() const = 0;
    virtual std::list<int>::const_iterator end() const = 0;

    virtual void push_back(int value) = 0;

    /* ... etc. ... */
};
既然您有了这个包装器,就可以实现
f
,这样它就可以接受
列表

class MyClass {
public:
    void f(List* myList) {
        myList->push_back(137); // For example
    }
};
您可以对看起来像列表的对象调用此函数,方法是首先将其包装到类型为
listempl
的对象中。对于exmaple:

MyClass mc;
std::list<int> myList;
MyIntList myIntList;

mc->f(new ListImpl<std::list<int> >(myList));
mc->f(new ListImpl<MyIntList>(myIntList));
您现在可以编写
f
来接收
ListWrapper
,如下所示:

void f(IntList l){...}
void f(KindaIntList l){...}
class MyClass {
public:
    virtual void f(ListWrapper list) {
        list.push_back(137); // For example
    }
};
(这假设您已使用虚拟的
clone
函数更新了
List
listempl
,该函数生成对象的副本,为了简洁起见,我省略了该函数)

神奇的是,该代码现在是合法的(而且安全的!):

MyClass-mc;
std::列表myList;
MyIntList MyIntList;
mc.f(myList);
mc.f(myIntList);
这段代码之所以有效,是因为
ListWrapper
的模板构造函数将自动推断其参数的类型,并隐式创建适合该对象的
ListImpl
类型的对象。它还为您封装了内存管理,因此您永远不会看到任何显式的
new
s或
delete
s。此外,这意味着您可以传入任何您想要的对象,并且所有内容都将自动工作-我们通过使用并行类层次结构,基本上使任何看起来像<代码>列表多态的内容都可以


唷!真有趣!希望这有帮助 在这种情况下,您不需要担心内联。除非在类的主体内部定义
f
,否则它不会自动内联,即使它是一个模板。例如,在此代码中:

class MyClass {
public:
     template <typename T> void f(T&);
};

template <typename T> void MyClass::f(T&) {
    /* ... implementation ... */
}
或者,您可以为模板实现创建一个单独的
.h
文件,然后在头文件的底部包含该文件。这会使客户机看不到模板实现,除非他们主动去寻找它

希望这有帮助

EDIT:如果
f
是虚拟的,那么您就不能将其作为模板函数(您可能已经知道)。因此,如果您想让它适用于“碰巧看起来像
std::list
”的事情,那么您没有很多好的选择。通常,您会为
std::list
和自定义列表类型创建一个基类,但这不是一个选项,因为您不能修改
std::list

幸运的是,有一种方法可以处理
std::list<