c++ - 函数模板 : Access Child Class' Overloaded Function In Base Class

标签 c++ templates

我有一个基类 First和派生类 Second .在基类中有一个成员函数 create和一个虚函数 run .在 Second 的构造函数中我想调用函数 First::create ,它需要访问其子类的实现'run()功能。自 First 以来,一位同事建议使用函数模板无法明确知道它的子类。听起来怪怪的?这是一些代码:

First.h

#pragma once
#include <boost/thread/thread.hpp>
#include <boost/chrono/chrono.hpp>

class First
{
public:
    First();
    ~First();

    virtual void run() = 0;
    boost::thread* m_Thread;
    void create();

    template< class ChildClass >
    void create()
    {
        First::m_Thread = new boost::thread(
            boost::bind( &ChildClass::run , this ) );
    }
};

First.cpp

#include "First.h"

First::First() {}
First::~First() {}

第二.h

#pragma once
#include "first.h"

class Second : public First
{
public:
    Second();
    ~Second();

    void run();
};

第二个.cpp

#include "Second.h"
Second::Second()
{
    First::create<Second>();
}

void Second::run()
{
    doSomething();
}

我在 First::create<Second>(); 处遇到错误说错误:不允许类型名称。那么这个错误的原因是什么?我想我还没有完全了解模板的全部机制,但我对这个主题还很陌生。

最佳答案

虽然您可以按照 Kerrek SB 和 Arne Mertz 的“建议”使用 CRTP,但这里有一个使用成员函数模板的解决方案:

class First
{
public:
    First();
    ~First();

    virtual void run() = 0;
    boost::thread* m_Thread;

    // vvvvvvvvvvv this declares a non-template member function `create`
    void create(); // (better remove it)

    // vvvvvvvvvv this declares a member function template `create`
    template< class ChildClass >
    void create();
};

对于模板,您应该在头文件中提供定义,因为定义必须在需要它的每个 TU 中可用(而不仅仅是在一个 TU 中)。

最简单的方法是在类本身中提供成员函数模板或类模板成员的定义:

class First
{
public:
    /* ... */

    template< class ChildClass >
    void create()
    {
        // AFAIK, the `bind` is not required
        First::m_Thread = new boost::thread(&ChildClass::run,
                                            static_cast<ChildClass*>(this));
    }
};

现在,如果你想在Second中调用这个成员函数模板类,您必须显式提供模板参数:

void Second::any_function()
{
    create<Second>();
}

您的代码的一些其他(可能)问题:

  • 您没有虚拟 dtor,因此删除指向基类子对象的指针将调用 UB。
  • 需要有一个沮丧,因为&ChildClass::run类型为 void (Second::*)() .
  • createSecond 的构造函数中被调用,这将调用 Second::run (或您提供的任何模板参数),类中该函数的最终覆盖 Second 。如果您在派生自 Second 的类中覆盖该函数, 将不会在 Second 的构造函数中调用该覆盖.
  • 您的 First 的负责人应该 detachjoin提升线程,否则std::terminate如果在调用 dtor 时线程仍在运行,将被调用。
  • run在这个例子中不必虚拟,完全相同的代码可以在没有 run 的情况下工作是虚拟的,甚至在 First 中声明.

关于c++ - 函数模板 : Access Child Class' Overloaded Function In Base Class,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18377236/

相关文章:

c++ - 虚拟关键字似乎被忽略

c++ - 在不编写显式 setter 的情况下修改私有(private)类数据成员的便捷方法是什么?模板有用吗?

c++ - 逆向工程 OSX 用户诊断报告堆栈跟踪

c++ - 推断大多数模板对象的参数,但在调用模板函数时与其他对象一起显式?

c++ - 包含内部模板类的 C++ 模板类构造函数的正确语法

c++ - 为什么::(scope) 与空的左侧操作数一起使用?

c++ - gtkmm、strncpy 中文本字段的意外行为

javascript - 这个jquery如何在meteor助手中实现?

c++ - 从链表中删除一个节点运行但不删除任何东西

c++仿函数和函数模板