【问题标题】:Derive template type of derived class from base class pointer从基类指针派生派生类的模板类型
【发布时间】:2018-09-07 20:03:19
【问题描述】:

考虑以下几点:

  1. B
  2. 一个类D,它
    • 派生自类B
    • 有一个模板参数T,
    • 有一个T类型的成员变量x
  3. 一个模板函数F
    • 一个模板参数S
    • S 类型的参数 y。
  4. 一个指针p,它
    • 具有类型 B *
    • 指向类 D 的对象 o,模板参数 T 等于例如int
  5. 函数F不能修改。
  6. F 不能直接从 B 或 D 类调用

进一步考虑,只有指针 p 被给出,并且 F 应该被调用,参数 y 等于成员变量 x 对象 o(这意味着类型 S 等于 int)。

如何修改类 BD 来实现这一点?我猜需要某种机制来派生模板类型 T。但我不知道该怎么做。

相关代码如下:

文件 F.h:

#include <iostream>
//////////// Consider that the lines up to the next comment cannot be changed
template< typename S > void F( S y )
{
    std::cout << y <<  " of some type" << std::endl; 
}

template<> void F<>( int y )
{
    std::cout << y << " of int type." << std::endl; 
}
//////////// -----------------------------

文件 BD.h:

// F.h cannot be included here
class B { };

template<typename T> class D : public B { public:  T x;  };

文件main.cpp:

#include "BD.h"
#include "F.h"
int main()
{
    D<int>  o;
    o.x  =  3;
    B* p = &o;

    // Obviously, the following line will not work:
    // F( p->x );

    // Obviously, the following will work:
    F( ( (D<int>*) p)->x );

    // However, consider that 
    //   1) only p is given and
    //   2) that it is not known that p points to an object of type D<int>.
    // How to modify B or D to be able to invoke the correct instantiation of F here
    // , i.e. that for the type of "int"?
    return 0;
}

【问题讨论】:

  • 我试图缩小对核心问题的描述。实际上,我想要一个B类型的指针数组或向量,这样我就可以访问或处理具有不同模板参数T的D类对象,例如通过进一步扩展Bs 接口(甚至可能带有虚函数)。
  • 为什么不能包含F.h?这听起来像是一个 X-Y 问题,解决方案可能是绕过该限制。 (也许F 可以前向声明?)
  • 可以B 知道每个“可能” 派生的class D&lt;T&gt; 吗?
  • 顺便说一句,您应该避免以使现有答案无效的方式编辑您的问题。 (例如,您可以问另一个)。
  • @aschepler:首先,出于实际原因,我正在处理的(大型)项目中遇到依赖问题。这可能会得到解决,但是,对此的努力尚不清楚。其次,也是出于概念上的原因,因为应该可以在其他项目中使用 BD.h 而无需 F.h.

标签: c++ templates inheritance


【解决方案1】:

你可能会这样做

class B
{
public:
    virtual ~B() = default;
    virtual void f() const = 0;
};

template<typename T>
class D : public B
{
public:
    void f() const override { F(x); }
private:
    T x;
};

Demo

【讨论】:

  • 考虑到问题的第一个版本是如何提出的,这将是一个解决方案。但是,我有一个问题,即在定义 D 和 B 时,F 的声明/定义不可用。我会相应地更新问题。
【解决方案2】:

您可以使用回调和虚拟成员函数来调用它:

class B
{
public:
    virtual ~B() = default;
    virtual void call() const = 0;
};

template <typename T>
class D : public B
{
public:
    explicit D(T t, std::function<void(T)> cb)
        : x(std::move(t)),
          callback(std::move(cb))
    {
    }
    void call() const override
    {
        callback(x);
    }
private:
    T x;
    std::function<void(T)> callback;
};

int main()
{
    D<int> o(3, F<int>);
    B* p = &o;
    p->call();
)

Live Demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-22
    • 2014-06-16
    • 1970-01-01
    相关资源
    最近更新 更多