@daniil14056

Почему не работает new c++?

Ни как не могу обьект создать
пишет 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;
}
  • Вопрос задан
  • 1680 просмотров
Пригласить эксперта
Ответы на вопрос 2
vt4a2h
@vt4a2h Куратор тега C++
Senior software engineer (C++/Qt/boost)
В классе User не реализован метод:
virtual int compare(Comparator *t)=0;
C++ поддерживает ковариантность типов возвращаемых значений, но не ковариантность (контрвариантность) аргументов функций, для полиморфных методов.
Ответ написан
@Mercury13
Программист на «си с крестами» и не только
Есть такое понятие, как «принцип подстановки Барбары Лисков». Если подставить на место User класс Comparator, должно сойтись по типам. Но нет: User умеет сравнивать только с самим собой, а Comparator — с любым Comparator.

Теоретически должно было бы подойти такое (так называемая контравариантность). Но не работает ни в Си++, ни в Яве.
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;
    }
};

А по возвращаемому значению (если возвращается ссылка/указатель) может быть ковариантность, и она работает и в Си++, и в Яве.
class Father
{
public:
    virtual Father& foo();
    virtual ~Father() = default;
};

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


Как обойти. Есть два способа.
Способ 1. Пусть старой Явы.
int User::compare(Comparator *u)
{
    auto* v = dynamic_cast<User*>(u);
    if (!v)
        return false;
    return v->name > this->name;
}


Способ 2. Так называемый «странно рекуррентный шаблон».
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;
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы