【问题标题】:specialized template for subclass子类的专用模板
【发布时间】:2015-12-04 04:58:29
【问题描述】:

举一个简单的例子,有两个相关的问题。源代码 - 3个文件:

父.h:

#ifndef PARENT_H
#define PARENT_H

using namespace std;
#include <vector>

template <class CHILD_TYPE>
class PARENT
{
    public:
        class CHILD_DATA
        {
        public:
            vector<CHILD_TYPE *> child_ptrs;
            void dump_child_data();
        };
    static CHILD_DATA data;
};

template<class CHILD_TYPE>
void PARENT<CHILD_TYPE>::CHILD_DATA::dump_child_data()
{
    return;
}

#endif  /* PARENT_H */

child.h

#ifndef CHILD_H
#define CHILD_H

#include "parent.h"
using namespace std;

#include <string>
#include <algorithm>
#include <iostream>
#include <iterator>

class SPECIAL_CHILD : public PARENT<SPECIAL_CHILD>
{
    public:
        SPECIAL_CHILD (const string newname = "unnamed") : name (newname) {}
        string name;
};

template<>
void PARENT<SPECIAL_CHILD>::CHILD_DATA::dump_child_data()
{
    for (vector<SPECIAL_CHILD *>::iterator it = child_ptrs.begin(); it != child_ptrs.end(); it++)
    {
        cout << (*it)->name << endl;;
    }
    return;
}

#endif  /* CHILD_H */

main.cpp

#include <cstdlib>
#include "parent.h"
#include "child.h"

using namespace std;

int main(int argc, char** argv) {

    SPECIAL_CHILD c_a;
    SPECIAL_CHILD c_b("named");
    SPECIAL_CHILD c_c("named_again");
    c_a.data.dump_child_data();
    return 0;
}

问题 1: 此示例未构建:

main.cpp:12:未定义对 `PARENT::data' 的引用

为什么? Parent的成员名为data是公共的,我不能像自己的成员一样从子类对象访问它吗?

问题 2:如何在超类中为子类创建专用模板 - 在我的例子中,模板参数是指向子类对象的指针?我绝对不希望超类知道有关子类的任何信息。我应该像我一样将专门的模板定义放在子类标题中吗?或者甚至在子类 .cpp 中,如果存在的话?

谢谢。

【问题讨论】:

  • 避免使用using namespace,尤其是在头文件中。

标签: c++ templates inheritance template-specialization


【解决方案1】:

对于第一季度,由于datastatic 成员,我认为您需要像这样访问它:

PARENT<SPECIAL_CHILD>::data.dump_child_data();

【讨论】:

    【解决方案2】:

    对于问题 1: 将此行添加到 您的一个 cpp 文件 parent.h

    template <class CHILD_TYPE>
    typename PARENT<CHILD_TYPE>::CHILD_DATA PARENT<CHILD_TYPE>::data;
    

    --已编辑--

    来自 N3797,第 14.5.1.3 条

    可以在包含静态成员类模板定义的命名空间范围内提供静态数据成员或静态数据成员模板的定义。

    --结束编辑--

    问题2:你是这个意思吗?

    class SPECIAL_CHILD : public PARENT<SPECIAL_CHILD*>
    {
    public:
        SPECIAL_CHILD (const string newname = "unnamed") : name (newname) {}
        string name;
    };
    

    【讨论】:

    • Danh,至于问题 1,在我当前的示例中,我没有子类的 cpp,我将所有内容都放在了标题中。我会将所有定义从 child.h 移动到 child.cpp 并试一试。至于问题2 - 不,我仍然希望超类模板参数是子类,而不是指向子类的指针。我对如何定义专门版本的 dump_child_data 感到沮丧,该版本仅适用于 SPECIAL_CHILD 类。
    • 对于问题2,我不明白你的意思。您的示例仅针对 SPECIAL_CHILD 描述了正确的 dump_child_data 专用版本
    • 对于问题 2:我的沮丧是我是否必须在头文件中提供一个专门的模板 definition,就像我对模板所做的那样。我猜不是,因为专用模板可能不再是模板,而是一个函数。当我在实际项目的头文件中提供专门的模板定义时,出现链接错误,指出此函数已定义多次 - 在使用此头文件构建的每个目标文件中。
    • 第二个问题:可以在头文件中提供特化定义,在别处提供定义。或者,您可以将定义放在该头文件中并将其标记为inline
    • 是的,这毕竟是我所做的(在标题中声明了专门的模板函数,但将定义移至 .cpp)。谢谢。
    猜你喜欢
    • 2015-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-04
    • 1970-01-01
    • 1970-01-01
    • 2013-01-08
    • 1970-01-01
    相关资源
    最近更新 更多