#c
#c
Вопрос:
Я пытаюсь сделать следующее: у меня есть класс Person, в котором я хочу иметь возможность использовать любую реализацию абстрактного класса Animal, поэтому я хочу иметь возможность создавать несколько пользователей в основном методе, причем каждый из этих пользователей может использовать либо собак, либо кошеки т. Д., И эти люди должны использовать конкретную реализацию метода doSomething() от конкретной собаки, кошки и т. Д. Реализация прямо сейчас не работает, я знаю, компилятор, конечно, говорит, что Animal не может использовать метод doSomething() (поскольку он виртуальный). Как я могу добиться того, что я пытаюсь сделать здесь?
person.h
#include <animal.h>
class Person
{
public:
Person();
~Person();
Animal *ani;
};
Person::Person (Animal *pointer)
{
ani = new Animal ();
}
Person::SomeMethod ()
{
ani->doSomething ();
}
Person::~Person ()
{
delete ani;
}
animal.h
class Animal
{
public:
Animal();
~Animal();
virtual void doSomething () = 0;
};
class Dog : public Animal
{
public:
Dog();
~Dog();
void doSomething ();
};
Dog::Dog ()
{
std::cout << "I've been created!" << std::endl;
}
Dog::doSomething ()
{
std::cout << "Hello" << std::endl;
}
main.h
#include <animal.h>
#include <person.h>
int main()
{
Dog *bowser;
Person *will = new Person (bowser);
return 0;
}
Комментарии:
1.
ani = new Animal ();
необходимо изменить на нужный вам класс, а не на базовый класс.2. «У Animal нет метода doSomething() (поскольку он виртуальный)». А?
3. @LightnessRacesinOrbit исправил это, извините за путаницу
4. @NathanOliver: Да, я знаю, что это можно было бы сделать таким образом, но в классе Person я хочу иметь возможность использовать любой реализованный класс Animal, то есть dogs, cats и т. Д.
5. Попробуйте написать этот пример без
new
, и это может иметь больше смысла. Используйте толькоDog dog;
, например, затем возьмитеAnimal* bowser = amp;dog;
где-нибудь. Вы получаете полиморфное поведение от указателя наAnimal
базовый класс.
Ответ №1:
Вот пример Person
принятия любого Animal
:
#include <iostream>
class Animal
{
public:
Animal() = default;
virtual ~Animal() {};
virtual void doSomething() = 0;
};
class Person
{
public:
Person(Animal* pointer);
~Person();
void SomeMethod();
Animal *ani;
};
Person::Person(Animal *pointer)
: ani{pointer} // initialize from passed pointer
{
//ani = new Animal(); //Person doesn't create/own an animal
}
void Person::SomeMethod()
{
ani->doSomething();
}
Person::~Person()
{
//delete ani; // Person doesn't own animal
}
class Dog : public Animal
{
public:
Dog();
~Dog() = default;
void doSomething();
};
Dog::Dog()
{
std::cout << "I've been created!" << std::endl;
}
void Dog::doSomething()
{
std::cout << "Hello" << std::endl;
}
int main()
{
Dog bowser; // no new here, RAII will take care of killing the Dog
Dog* bowser_ptr = amp;bowser;
Person will(bowser_ptr);
will.SomeMethod();
return 0;
}
Вот пример Person
владения случайным Animal
:
#include <vector>
#include <iostream>
#include <random>
#include <exception>
class Animal
{
public:
Animal() = default;
virtual ~Animal() {}; // must be virtual!
virtual void doSomething() = 0;
};
class Dog : public Animal
{
public:
Dog();
~Dog();
void doSomething();
};
class Cat : public Animal
{
public:
Cat();
~Cat();
void doSomething();
};
Animal* get_random_animal()
{
static std::random_device rd;
static std::mt19937 gen(rd());
static std::uniform_int_distribution<> dis(1, 2);
switch(dis(gen)) {
case 1:
return new Dog;
case 2:
return new Cat;
default:
throw std::runtime_error{"Not sure which animal."};
}
}
class Person
{
public:
Person();
Person(Personamp;amp;) = delete; // person contains raw pointers, we must either delete or specify the move constructor
Person(const Personamp;) = delete; // person contains raw pointers, we must either delete or specify the copy constructor
Personamp; operator=(Personamp;amp;) = delete; // person contains raw pointers, we must either delete or specify the move assignment operator
Personamp; operator=(const Personamp;) = delete; // person contains raw pointers, we must either delete or specify the copy assignment operator
~Person();
void SomeMethod();
Animal *ani;
};
Person::Person()
: ani{get_random_animal()} // initialize with random animal
{
}
void Person::SomeMethod()
{
ani->doSomething();
}
Person::~Person()
{
delete ani; // Person does own animal
}
Dog::Dog()
{
std::cout << "I've been created! Woof!" << std::endl;
}
Dog::~Dog()
{
std::cout << "I've been destroyed! Woof!" << std::endl;
}
void Dog::doSomething()
{
std::cout << "Woof" << std::endl;
}
Cat::Cat()
{
std::cout << "I've been created! Meow!" << std::endl;
}
Cat::~Cat()
{
std::cout << "I've been destroyed! Meow!" << std::endl;
}
void Cat::doSomething()
{
std::cout << "Meow" << std::endl;
}
int main()
{
Person will;
will.SomeMethod();
std::cout << "n More people with animals: n";
std::vector<Person> people(10);
return 0;
}
Пример вывода:
I've been created! Meow!
Meow
More people with animals:
I've been created! Woof!
I've been created! Meow!
I've been created! Meow!
I've been created! Meow!
I've been created! Meow!
I've been created! Meow!
I've been created! Woof!
I've been created! Meow!
I've been created! Woof!
I've been created! Woof!
I've been destroyed! Woof!
I've been destroyed! Meow!
I've been destroyed! Meow!
I've been destroyed! Meow!
I've been destroyed! Meow!
I've been destroyed! Meow!
I've been destroyed! Woof!
I've been destroyed! Meow!
I've been destroyed! Woof!
I've been destroyed! Woof!
I've been destroyed! Meow!
Комментарии:
1. Проблема с вашим решением заключается в том, что объекты должны быть созданы в main, но у меня есть много функций лично (которые должны оставаться там), которые необходимы для создания объекта Animal…
2. извините, я ничего не могу с этим поделать, вы слишком много изменили в моем дизайне…