【问题标题】:Polymorphism and overriding a method from a class template in C++ [duplicate]多态性和从 C++ 中的类模板重写方法 [重复]
【发布时间】:2015-05-07 14:38:02
【问题描述】:

我想要一个类模板,其中包含我的方法的基本实现,以及一组子类,这些子类使用具有特定类型(double、int、char*)的模板类并根据需要覆盖这些基本实现的某些子集.但是,除非我将对象声明为子类的实例,否则我的重写方法似乎不会被调用。在探索这个问题时,我想出了以下代码:

#include <iostream>

template <typename T>
class BaseClass {
public:
    virtual void print1 (T thing) {
        std::cout << "Base print1: " << thing << std::endl;
    }

    virtual void print2 (T thing) {
        std::cout << "Base print2: " << thing << std::endl;
    }
};

class IntClass : public BaseClass<int> {
public:
    void print2 (int thing) {
        std::cout << "Int print2: " << thing << std::endl;
    }
};

int main()
{
    BaseClass<int> thing = IntClass();
    thing.print1(1);
    thing.print2(1);

    IntClass thing2 = IntClass();
    thing2.print1(2);
    thing2.print2(2);

    return 0;
}

我的预期输出是:

Base print1: 1
Int print2: 1
Base print1: 2
Int print2: 2

但相反,我得到:

Base print1: 1
Base print2: 1
Base print1: 2
Int print2: 2

是否有可能在这里实现我的目标,或者在这种情况下我最好为每种类型创建单独的基类?抱歉,如果我的术语有点偏离 - 我对 C++ 比较陌生。

【问题讨论】:

    标签: c++ templates polymorphism overriding


    【解决方案1】:

    thing 的类型是 BaseClass&lt;int&gt;,而不是 IntClass。在复制BaseClass 子对象后,您用来初始化它的临时IntClass 已被销毁。像这样复制对象的一部分有时称为切片

    当您使用对基类的引用或指针时,多态会起作用,基类可能引用派生类的对象。因此,您将通过引用 IntClass 对象获得预期结果:

    // In C++11 or later, you can bind an rvalue reference to a temporary, extending its lifetime
    BaseClass<int> && thing = IntClass();
    
    // If you're stuck in the past, you can bind an lvalue reference to a variable
    IntClass ic;
    BaseClass<int> & thing = ic;
    

    【讨论】:

    • 好的,这很有道理。但是我无法让您建议的代码行正常工作。我错过了什么吗? error: expected unqualified-id before &amp;&amp; token
    • @diagonalfish:如果你有一个古老的编译器,或者没有指定 C++11 或 C++14 方言,那么它可能不知道什么是 rvalue i> 参考是。在这种情况下,您可以尝试IntClass ic; BaseClass&lt;int&gt; &amp; thing = ic; 或按照另一个答案的建议使用动态分配。
    • 啊哈,是的,-std=c++11 做到了。惊人的。谢谢。
    【解决方案2】:

    如果您使用指针,您将获得预期的结果。但是,正如我对这个答案的简短研究所了解到的那样,这里发生的是那个“事物”——称为事物的对象;不是参数,取 IntClass 中属于 BaseClass 的部分,并简单地丢弃其余部分。这称为对象切片。

    【讨论】:

      【解决方案3】:

      BaseClass&lt;int&gt; thing = IntClass();

      这并不像你认为的那样。它创建IntClass 的临时实例,然后将其复制到thing 类型为BaseClass&lt;int&gt;。结果称为对象切片(您可以搜索)。

      在这种情况下,由于派生类型在编译时已知,因此没有理由不使用IntClass 作为thing 的类型。但是对于一般用途,您需要使用指针。这是一个例子:

      std::unique_ptr<BaseClass<int>> thing(new IntClass);
      thing->print1(1);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-06
        • 2018-07-08
        • 2019-09-06
        • 2016-04-12
        • 1970-01-01
        • 1970-01-01
        • 2011-02-20
        • 1970-01-01
        相关资源
        最近更新 更多