C++模板函数、继承shared_ptr

C++ template function, inheritance, shared_ptr

提问人:duncan 提问时间:11/4/2023 更新时间:11/4/2023 访问量:66

问:

我想这是一个非常基本的问题,但我仍然在问,因为我怀疑编译器按预期运行,而错误来自我!

我想用模板抽象函数实现一个抽象类。如您所知,这是不可能的:模板函数不能是抽象的。

因此,我必须在我的基类中实现一个虚拟函数。 由于多种原因不方便,但就这样吧。

问题在于,一旦我使用指针,编译器就会调用基类函数,而不是子类实现。

如何解决这个问题?


#include <iostream>
#include <memory>

class Person
{
  protected:
    std::string _first_name;
    std::string _last_name;

  public:
    Person(std::string first_name, std::string last_name):
        _first_name(first_name), _last_name(last_name){}

    const std::string & first_name() const { return _first_name; }
    const std::string & last_name() const { return _last_name; }
};

// ==============================================================================
// Using template functions.

class HumanPrinterBase
{
  public:
    template <typename T>
    void print(const T & person) const { std::cout << "HumanPrinterBase::print()" << std::endl; }
};

class HumanFirstNamePrinter : public HumanPrinterBase
{
  public:
    template <typename T>
    void print(const T & person) const
    {
        std::cout << person.first_name() << std::endl;
    }
};


// ==============================================================================
// Using non-template functions.

class PersonPrinterBase
{
  public:
    virtual ~PersonPrinterBase() = default;
    virtual void print(const Person & person) const = 0;
};

class PersonFirstNamePrinter : public PersonPrinterBase
{
  public:
    virtual void print(const Person & person) const override
    {
        std::cout << person.first_name() << std::endl;
    }
};


int main(int argc, char const *argv[])
{
    Person person("John", "Doe");

    std::unique_ptr<HumanPrinterBase> hp = std::make_unique<HumanFirstNamePrinter>();
    hp->print(person); // "HumanPrinterBase::print()" (fails)

    std::unique_ptr<PersonPrinterBase> pp = std::make_unique<PersonFirstNamePrinter>();
    pp->print(person); // "John" (works)

    return 0;
}

C++ 模板 继承 shared-ptr unique-ptr

评论

0赞 Pepijn Kramer 11/4/2023
不,要使动态多态性起作用,您需要一个具有虚函数的抽象基类,而不是模板类(静态多态性)。你应该有一个纯虚函数(和虚析构函数):(其中 PersonBase 是另一个纯抽象基类)HumanPrinterBasevirtual void print(const PersonBase& person) = 0;
0赞 Yksisarvinen 11/4/2023
首先想到的是 CRTP,但这个问题设计得太过分了,以至于很难猜测要解决的实际问题是什么,以及解决方案应该满足什么条件。
0赞 Pepijn Kramer 11/4/2023
有一些方法可以只使用模板(静态多态性)来做到这一点,但这根本不涉及继承(除了@Yksisarvinen所说的 CRTP 来混合可重用代码)。使用 std::shared_ptr 时也要小心,它不应该是你的首选(我只在多线程场景中使用它)
0赞 Mooing Duck 11/4/2023
这类似于 Double Dispatch,但添加模板会在正常解决方案中遇到麻烦。
1赞 n. m. could be an AI 11/4/2023
C++ 不是面向对象的语言。它是一种多范式语言,对面向对象编程有一些基本的支持。

答: 暂无答案