【问题标题】:Specialize a method form base class in a derived template class在派生模板类中特化方法形式基类
【发布时间】:2016-04-16 12:26:21
【问题描述】:

我很难弄清楚我应该如何进行模板专业化。这一次,不幸的是,google 和 SO 帮不了我。

对于基类:

class base
{
public:
    virtual ~base() = 0;

    virtual int getInt() { throw std::invalid_argument(std::string(typeid(*this).name()) + " can't return int"); }
};
base::~base() {}

和派生类:

template<class T>
class derived : public base
{
public:
    derived() {}
    derived(T value) { mValue = value; }

private:
    T mValue;
};

这段代码:

void proof(base* arg)
{
    try
    {
        std::cout << arg->getInt();
    }
    catch (std::exception& e)
    {
        std::cout << e.what();
    }
    std::cout << "\n\n";
}

int main()
{
    base* a = new derived<int>(23);
    base* b = new derived<std::string>("abc");

    proof(a);
    proof(b);

    delete a;
    delete b;

    return 0;
}

输出,如果不是很明显:

class derived<int> can't return int

class derived<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > can't return int

我应该如何对派生进行专门化,以便 getInt() 返回 mValue ?比如:

template<>
int derived<int>::getInt() { return mValue; } 

这不起作用。

为了更清楚,我希望在调用 arg->getInt() 时输出 23,并且在调用 arg->getInt() 时在基类中抛出异常。 你能给我一个示例代码吗?谢谢。

【问题讨论】:

  • 默认构造函数看起来是个糟糕的主意!它是什么意思
  • 我正在尝试封装一些数据类型,以便可以制作多种数据类型的向量。注意: int 只是一个例子,我确实有另一个不封装基本类型的类。

标签: c++ class inheritance polymorphism


【解决方案1】:

derived 模板没有getInt() 方法。你不能专门化不存在的东西。

您必须专门化整个模板。试试这个:

template<>
class derived<int> : public base
{
public:
    derived() {}
    derived(int value) { mValue = value; }
    int getInt() override { return mValue; } 
private:
    T mValue;
};

【讨论】:

  • 如果这是唯一的解决方案,那么我将不得不一遍又一遍地制作类以进行封装。这正是我不想做的:写同一个类 10 次,但使用不同的数据类型。感谢您的帮助。你确定这是唯一的方法吗?
  • 是的,这就是专业化在 C++ 中的工作方式。我确信还有其他设计类层次结构的方法,这些方法以不同的方式利用专业化。例如,您可以创建“template class not_really_derived : public base {};”,只为您的 getInt() 专门化“not_really_derived”,然后使用 derived 子类 not_really_derived 而不是基础,没有专业化。
【解决方案2】:

您可以将模板专门用于int

template <> class derived<int> : public base
{
public:
    derived(int value) : mValue(value) {}

    int getInt() override { return mValue; }

private:
    int mValue;
};

【讨论】:

  • 感谢您帮助我。但不是另一种解决方案,所以我可以只专注于那个功能吗?
  • @AndreiAndrey:您始终可以通过中间辅助基类来分解此模式,因此您不必重复任何通用代码。这只是蛋糕的成分之一,其他的还得带上。
  • 去找一只鸡,我去拿鸡蛋。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-10
  • 2018-01-22
  • 2016-08-17
  • 1970-01-01
  • 2014-03-22
  • 2019-02-07
  • 1970-01-01
相关资源
最近更新 更多