RomaFUN
RomaFUN

Reputation: 59

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

I have a parent class Obj with empty virtual function cmp

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

I am trying to define that function in the subclass MyString, but instead of const Obj& as argument, i use const MyString& which probably occures the error "Emprty virtual function Obj::cmp has no redifinition"

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

So how can i solve that, if i have 3-4 subclasses which uses their own variables in that function

Upvotes: 4

Views: 763

Answers (2)

Gor Asatryan
Gor Asatryan

Reputation: 924

If you want to use overriding you have to define method in subclasses as it is in base class and can't change parameters of virtual function. In method of subclass you can cast to a type you need.

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
        }
};

Also you can use overloading. In this case you don't need virtual method in base 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
        }
};

Upvotes: 2

nurettin
nurettin

Reputation: 11736

An example that comes to my mind is the curiously recurring template pattern. It goes like this:

#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;
}

Upvotes: 3

Related Questions