D
D
Daniel2018-10-12 22:29:55
C++ / C#
Daniel, 2018-10-12 22:29:55

Why doesn't new c++ work?

No way I can create an object
writes error: invalid new-expression of abstract class type 'User'

#include <iostream>

class Comparator{
    public: 
        virtual int compare(Comparator  *t)=0;
};

class User : public Comparator{
private:
    std::string name;
public: 
    User(std::string name){this->name=name;}
    int compare(User *u){
        return u->name>this->name;
    }
    void showName(){std::cout<<"Name "<<this->name<<std::endl;}

};

int main(int argc, char**argv) {.
   
    User> *u;
    std::string name="Daniil";
    u=new User(name);// error: invalid new-expression of abstract class type 'User'
    u->showName();
    
    delete u;
    
   
    return 0;
}

Answer the question

In order to leave comments, you need to log in

2 answer(s)
V
Vitaly, 2018-10-12
@vt4a2h

Method not implemented in User class: C++ supports covariance of return types, but not covariance (contravariance) of function arguments, for polymorphic methods.

M
Mercury13, 2018-10-12
@Mercury13

There is such a thing as the “Barbara Liskov substitution principle”. If we substitute the Comparator class in place of the User, the types should converge. But no: User can only compare with itself, while Comparator can compare with any Comparator.
Theoretically, this should be suitable (the so-called contravariance). But it doesn't work in C++ or Java.

class ComparatorBase
{
public:
    virtual ~ComparatorBase() = default;
};

class Comparator : public ComparatorBase {
    public:
        virtual int compare(Comparator  *t)=0;
};

class User : public Comparator{
public:
    int compare(ComparatorBase *u) override {
        return 1;
    }
};

And on the returned value (if a reference/pointer is returned) there can be covariance, and it works in both C++ and Java.
class Father
{
public:
    virtual Father& foo();
    virtual ~Father() = default;
};

class Son : public Father
{
public:
    Son& foo() override;
};

How to bypass. There are two ways.
Method 1. Let old Java.
int User::compare(Comparator *u)
{
    auto* v = dynamic_cast<User*>(u);
    if (!v)
        return false;
    return v->name > this->name;
}

Method 2. The so-called "weird recurrent pattern".
template <class T>
class Comparator {
public:
    virtual int compare(T *t)=0;
    virtual ~Comparator() = default;
};

class User : public Comparator<User> {
private:
    std::string name;
public:
    User(std::string name){this->name=name;}
    int compare(User *u);
    void showName(){std::cout<<"Name "<<this->name<<std::endl;}

};

int User::compare(User *u)
{
    return u->name > this->name;
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question