Возможно ли переопределение методов объекта? С++

Мне было интересно, можно ли переопределить метод объекта бывший:

class Object{
public:
  void Foo(){
  //do something
  }
};

Object* obj = new Object();

obj->Foo() {
//do something else
}

Я пытался использовать функциональную переменную, но она все равно не работает.

Пожалуйста, помогите, я чувствую, что вот-вот потеряю мозги из-за этой проблемы.

Вместо этого у вас есть участник std::function?

Jarod42 26.06.2024 18:53

Кажется, вы просите о функциональной переменной, поэтому я опубликую код, который не работает, чтобы люди могли вам в этом помочь.

john 26.06.2024 19:02

Нет, вам придется объявить подкласс и вместо этого создать экземпляр объекта подкласса.

Jeremy Friesner 26.06.2024 19:03

Совершенно не связанное с этим тактическое примечание: здесь нет необходимости использовать new, чтобы получить экземпляр Object, и это, вероятно, навредит вам несколькими способами. Object obj; сделает все, что вам нужно, без необходимости дорогостоящего динамического распределения и необходимости вручную управлять временем жизни экземпляра. Это сбивает с толку многих новых программистов, которые переходят на C++ из языка, где new — единственный способ получить экземпляр объекта. В C++ new — это один из последних инструментов, к которым вам следует обратиться, и его лучше всего использовать для написания низкоуровневого служебного кода.

user4581301 26.06.2024 20:15

@Jarod42 спасибо за идею, она действительно работает так, как я хотел, чтобы она работала сейчас.

light drop 26.06.2024 23:27

@user4581301 user4581301 Мне нужно вызвать new, потому что я хочу сохранить его как указатель, чтобы я мог передавать его другим функциям, а что нет, но спасибо за предложение

light drop 26.06.2024 23:28
newпока не обязательно. Вы можете передать указатель на любой объект с помощью оператора адреса. например: myfunc(&obj); Примечание: избегайте использования указателя, если вместо него можно использовать ссылку. Передать плохую ссылку труднее, чем передать плохой указатель.
user4581301 27.06.2024 01:20
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
7
100
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Как упомянул @Jarod42 в комментариях, я бы добавил участника std::function или другого вызываемого участника. Как пример (Годболт)

#include <functional>
#include <iostream>
#include <utility>

class Object {
public:
   Object(std::function<int(int)> do_work) : do_work_(std::move(do_work)) {}

   int DoWork(int i) { return do_work_(i); }

private:
   std::function<int(int)> do_work_;
};

int main() {
  Object obj1{[](int i){ return i + 1;}};
  std::cout << obj1.DoWork(1) << '\n';

  Object obj2{[](int i){ return i - 1;}};
  std::cout << obj2.DoWork(1) << '\n';
}

Вы можете видеть, что DoWork вызывает вызываемый объект, и каждый экземпляр класса Object может свободно определять, что это за работа.

Нет, члены функции не являются данными в C++, поэтому их нельзя изменять отдельно для каждого объекта. Нет obj->Foo(); есть только Object::Foo(), который получает скрытый параметр this, указывающий на *obj.

Если вам нужно разрешить пользователю вашего класса настраивать поведение класса, у вас есть два основных варианта:

  1. Используйте в классе функцию-член (возможно, чистую) virtual и позвольте пользователям создавать новый дочерний класс из вашего класса:
class Object {
public:
    virtual void Foo() {
        // do something
    }
};

class DerivedObject {
public:
    void Foo() override {
        // Do something else
    }
};

int main() {
    Object* obj = new DerivedObject();
    obj->Foo(); // will call DerivedObject::Foo()
}

Это немного усложняет обработку объекта, поскольку теперь вам нужно всегда передавать указатели и ссылки, что может потребовать динамического выделения, когда статически типизированный объект этого не требует. Преимущество этого метода заключается в том, что пользователи могут добавлять к объекту дополнительное состояние для работы своих пользовательских функций. Например, DerivedObject может иметь дополнительные элементы данных, к которым DerivedObject::Foo может получить доступ для выполнения своей работы.

  1. Используйте член функционального объекта:
class Object {
public:
    Object(std::function<void(Object*)> foo)
        : foo_{std::move(foo)}
    {}

    Object()
        : foo_{[](Object* self) { /* do something */ }}
    {}

    void Foo() {
        foo_(this);
    }

private:
    std::function<void(Object*)> foo_;
};

int main() {
    Object o{[](Object* self) {
        // do something else
    }};
    o.Foo();
}

Это упрощает обработку Object объектов, поскольку нормальная семантика значений по-прежнему сохраняется. Вы можете копировать, назначать, передавать по значению и т. д. без потери какой-либо информации об объекте. Однако по умолчанию член функционального объекта не имеет доступа к самому объекту. Вам нужно будет либо захватить ссылку или указатель на объект, либо передать его объекту функции каждый раз, когда он вызывается. В примере я сделал последнее, так как первое обычно не работает при копировании объектов.

Другие вопросы по теме