如何定义以派生类型为参数的虚函数?

How can I define virtual function which takes derived type as its parameter?

我有一个带有空虚函数 cmp 的父对象 class Obj

class Obj{
 public:
   virtual int cmp(const Obj& val) = 0;
   ...
};

我试图在 subclass MyString 中定义该函数,但我使用 const MyString& 作为参数而不是 const Obj&,这可能会出现错误“Emprty virtual function Obj::cmp 没有重新定义

class MyString : public Obj{
private:
    ...
public:
    virtual int cmp(const MyString& val){
        ... using private values of MyString
    }
};

如果我有 3-4 个在该函数中使用自己的变量的子class,我该如何解决这个问题

如果你想使用重写,你必须在子classes 中定义方法,因为它在基础class 中,并且不能更改虚函数的参数。在 subclass 的方法中,你可以转换为你需要的类型。

class Obj
{
    public:
        virtual int cmp(const Obj& val) = 0;
        ...
};

class MyString : public Obj
{
    private:
        ...
    public:
        int cmp(const Obj& val)
        {
            // cast val to MyString& (you can use dynamic_cast)
            ... using private values of MyString
        }
};

您也可以使用重载。在这种情况下,您不需要基 class.

中的虚拟方法
class Obj
{
    public:
        int cmp(const Obj& val)
        {
             // implementation for Obj
        }
        ...
};

class MyString : public Obj
{
    private:
        ...
    public:
        int cmp(const MyString& val)
        {
            ... using private values of MyString
        }
};

我想到的一个例子是 curiously recurring template pattern. 它是这样的:

#include <iostream>
#include <ostream>

template <typename T>
struct Base
{
    virtual int cmp(T const &) = 0;
};

struct First : Base<First>
{
    virtual int cmp(First const &);
};

int First::cmp(First const &)
{
    std::cout << "First\n";
    return 1;
}

struct Second : Base<Second>
{
    virtual int cmp(Second const &);
};

int Second::cmp(Second const &)
{
    std::cout << "Second\n";
    return 2;
}

int main()
{
    Base<First>* f1 = new First();
    Base<First>* f2 = new First();
    Base<Second>* s = new Second();
    f1->cmp(*dynamic_cast<First*>(f2)); // if this will throw, use RAII instead of deletes below
    // f1->cmp(*dynamic_cast<Second*>(f2)); error: cannot convert Second to First
    delete f1;
    delete f2;
}