У меня есть следующий фрагмент кода:
#include <iostream>
class AnimalRepository {
public:
virtual ~AnimalRepository() = default;
virtual auto makeSound() -> void {
std::cout << "Null" << std::endl;
}
};
class CatRepository: public AnimalRepository {
public:
auto makeSound() -> void override {
std::cout << "Meow" << std::endl;
}
};
class DogRepository: public AnimalRepository {
public:
auto makeSound() -> void override {
std::cout << "Woof" << std::endl;
}
};
class Animal {
public:
explicit Animal(const AnimalRepository& repository)
: repository(repository) {
}
auto makeSound() -> void {
return repository.makeSound();
}
protected:
AnimalRepository repository;
};
Animal cat = Animal(CatRepository());
Animal dog = Animal(DogRepository());
int main() {
cat.makeSound();
dog.makeSound();
};
Я ожидал, что основная функция выведет соответствующие функции переопределения методов кошек и собак, но вместо этого она всегда возвращает «Null». Я считаю, что это случай нарезки объекта, и я не совсем уверен, что понимаю, почему указатель ссылки в конструкторе класса Animal не позволяет избежать этой проблемы.
auto cat = std::make_unique<Animal>(Cat());вы вызываете Animal::makeSound, который вызывает repository::makeSound, который печатает Null. Непонятно, почему вы ожидали чего-то другого. Нарезки объектов нет (пока?), но вам нужны ссылки или указатели для динамической отправки. Но, пожалуйста, опубликуйте реальный код. Код, который вы опубликовали, не производит никакого вывода, потому что он не компилируется godbolt.org/z/q3WYz1fKs
Также кажется, что вы что-то упустили из-за ООП и наследования в своих книгах. Animal cat = Animal(Cat()); тоже не имеет смысла.
о Animal(Cat()); на самом деле это нарезка объектов
@Someprogrammerdude, это измененный пример того, что я пытаюсь сделать, переименованы только объекты, методы и переменные. Я бы предпочел просто сосредоточиться на проблеме, а не углубляться в семантику дизайна, так как это уже решено за меня и не изменится.
Animal::makeSound не является виртуальным. В вашем коде много непонятного. Чтобы получить помощь, вы должны по крайней мере опубликовать код, который компилирует и производит вывод, о котором вы сообщаете. Читайте о минимальном воспроизводимом примере@ 463035818_is_not_a_number у меня отлично компилируется. Единственное, что изменилось, это имена объектов, которые не должны иметь значения. Именно так и написано.
кстати AnimalRepository::makeSound является виртуальным, но ничего не наследует от него
Вы, кажется, перепутали Animal с AnimalRepository. Это объяснило бы многое.
@ 463035818_is_not_a_number ничего не изменилось, кроме имен классов. Я не знаю, что тебе сказать. Я ничего не получаю от постулирования невоспроизводимого примера, поэтому просто игнорируйте его. Спасибо
Ошибка @Someprogrammerdude при изменении имен для этого примера, проблема остается. Хотя спасибо за улов
Кажется, у вас тоже очень похожее задание, как у этого вчерашнего вопроса.
Вместо использования AnimalRepository repository я бы использовал AnimalRepository* repository (и очищал вручную) или std::unique_ptr<AnimalRepository> repository. Я подозреваю, что именно здесь происходит нарезка
Когда вы сохраняете в AnimalRepository repository;, остается место только для базового класса, поэтому эта часть сохраняется. Остальное потеряно. Это не имеет ничего общего с передачей параметров или чем-то еще, это просто то, как работает хранение.
@Someprogrammerdude не уверен, так как я не заинтересован в использовании карты, и у этого есть отдельная цель
Карта или вектор или другой контейнер не имеет значения. И теперь ваш дизайн имеет еще меньше смысла. Помните, что наследование — это отношение «является». Является ли «собака» действительно «хранилищем животных»? «Хранилище животных» - это место, где так или иначе хранится несколько животных, а не животное само по себе. Я действительно призываю вас вернуться к своим учебникам, чтобы освежиться, возможно, даже пойти к своему учителю и попросить ее или его о помощи.





Нарезка делается здесь: AnimalRepository repository;. Это не может содержать подкласс, потому что это экземпляр, а не ссылка или указатель. Проще всего заменить его уникальным интеллектуальным указателем, указывающим на копию ввода.
Или переместите весь шаблон из динамического полиморфизма в (время компиляции) статический полиморфизм.
#include <iostream>
class CatBehavior
{
public:
auto makeSound() -> void
{
std::cout << "Meow" << std::endl;
}
};
class DogBehavior
{
public:
auto makeSound() -> void
{
std::cout << "Woof" << std::endl;
}
};
template<typename behavior_t>
class Animal
{
public:
explicit Animal()
{
}
auto makeSound() -> void
{
return m_behavior.makeSound();
}
protected:
behavior_t m_behavior;
};
int main()
{
Animal<CatBehavior> cat;
Animal<DogBehavior> dog;
cat.makeSound();
dog.makeSound();
};
Ваш дизайн кажется ошибочным. Почему «животное» должно содержать хранилище разных животных? Если вы не думаете о паразитах, таких как блохи на собаке, это не имеет смысла.