【问题标题】:How to pass std::list of derived class instead of a std::list of parent class to a function?如何将派生类的 std::list 而不是父类的 std::list 传递给函数?
【发布时间】:2019-12-29 22:30:30
【问题描述】:

为什么第二次调用print_all 函数会导致静态语义错误

#include <list>
using std::list;
class foo {
    // ...
};
class bar : public foo {
    // ...
};

static void print_all(list<foo*>& L) {
    // ...
}

list<foo*> LF;
list<bar*> LB;
// ...
print_all(LF); // works fine 
print_all(LB); // static semantic error

【问题讨论】:

标签: c++ function class inheritance stdlist


【解决方案1】:

std::list 是一个模板类,意思是,需要用一个类型实例化,以获得所需模板类的完整类定义。当std::listfoobar 实例化时,我们得到完全不同的类型。这意味着bar 是一个 foo(由于继承),但std::list&lt;foo*&gt;std::list&lt;bar*&gt; 的类型不同。因此,根据给定的定义,print_all(std::list&lt;foo*&gt; &amp;L) 只能采用 指向foo 的指针列表

解决问题的最简单方法是templated function。将print_all 函数模板化为一个,它也可以接受其他类型(即std::list&lt;foo*&gt;std::list&lt;bar*&gt; 等...)。

template<typename Type>                   // --> template parameter
void print_all(std::list<Type*> const& L) // --> function parameter
//                              ^^^^^^ --------> use `const-ref` as the list is
//                                               not being modified inside the function
{ 
   // print the list   
}

不过,它现在也将接受其他类型,例如 std::list&lt;int*&gt;std::list&lt;float*&gt; 等。(所有其他可能的类型)。这可能不是您想要的行为。我们有所谓的 "Substitution Failure Is Not An Error" (SFINAE) 技术,通过该技术可以限制模板化print_all 函数的实例化,当且仅当模板Typestd::is_base_offoo班级。类似的东西

#include <type_traits> // std::enable_if, std::is_base_of

template<typename T>
auto print_all(std::list<T*> const& L)-> std::enable_if_t<std::is_base_of_v<foo, T>> // in C++14
// or
// auto print_all(std::list<T*> const& L)-> typename std::enable_if<std::is_base_of<foo, T>::value>::type // in C++11
{
    // print the list
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多