In the realm of psuedocode, if I wanted to act upon something in Java, I could go
class Dragon
{
//some code here defining what a Dragon is
}
class Knight
{
//some code here defining what a Knight is
public void Attack(Dragon dragon) // <----- specifically this
{
//define an attack
}
}
class Main
{
public static void main (String[] args)
{
Knight knight = new Knight;
Dragon dragon1 = new Dragon;
Dragon dragon2 = new Dragon;
knight.Attack(dragon1); // <----- specifically this
}
}
How would I do this in c ?
When I try to use the following code, I'm told that error: unknown type name 'Dragon'
#include <iostream>
#include <list>
#include <string>
class IObserver {
public:
virtual ~IObserver(){};
virtual void Update(const std::string &message_from_subject) = 0;
};
class ISubject {
public:
virtual ~ISubject(){};
virtual void Attach(IObserver *observer) = 0;
virtual void Notify() = 0;
};
class Knight : public ISubject {
public:
void Attach(IObserver *observer) override {
list_observer_.push_back(observer);
}
void Notify() override {
std::list<IObserver *>::iterator iterator = list_observer_.begin();
while (iterator != list_observer_.end()) {
(*iterator)->Update(message_);
iterator;
}
}
void CreateMessage(std::string message = "Empty") {
this->message_ = message;
Notify();
}
void Attack(Dragon dragon) { //<-----------right here
this->message_ = "I am attacking";
Notify();
std::cout << "todo\n";
}
private:
std::list<IObserver *> list_observer_;
std::string message_;
};
class Dragon : public ISubject {
public:
void Attach(IObserver *observer) override {
list_observer_.push_back(observer);
}
void Notify() override {
std::list<IObserver *>::iterator iterator = list_observer_.begin();
while (iterator != list_observer_.end()) {
(*iterator)->Update(message_);
iterator;
}
}
void CreateMessage(std::string message = "Empty") {
this->message_ = message;
Notify();
}
void CallForHelp() {
this->message_ = "I'm under attack";
Notify();
std::cout << "todo\n";
}
private:
std::list<IObserver *> list_observer_;
std::string message_;
};
class GameManager : public IObserver {
public:
GameManager(Knight &subject) : subject_(subject) {
this->subject_.Attach(this);
std::cout << "GameManager " << GameManager::static_number_ << " online\n";
this->number_ = GameManager::static_number_;
}
void Update(const std::string &message_from_subject) override {
message_from_subject_ = message_from_subject;
PrintInfo();
}
void PrintInfo() {
std::cout << "GameManager " << this->number_ << ": a new message is available --> " << this->message_from_subject_ << "\n";
}
private:
std::string message_from_subject_;
Knight &subject_;
static int static_number_;
int number_;
};
int GameManager::static_number_ = 0;
void ClientCode() {
Knight *knight = new Knight;
GameManager *gameManager = new GameManager(*knight);
knight->CreateMessage("I exist");
knight->CreateMessage("Going to attack dragon1");
knight->Attack();
}
int main() {
ClientCode();
return 0;
}
I must be missing something but I feel like this should work. I'm not super informed on abstract classes or c but there should be an equivalent action that's able to be made, right?
CodePudding user response:
C and C code, unlike Java, are compiled in a single pass, so classes cannot be referenced until after they are defined. When you reference the class Dragon
before defining class Dragon
the compiler doesn't recognize it. You must define class Dragon;
earlier in the code before it's used.
CodePudding user response:
In C , when a class or any other identifier is declared below, as far as the compiler knows it is undeclared. You will need to declare Knight below Dragon.
Also notice the distinction between passing a class as an argument by value, reference or pointer. In most cases you will want to pass a class by reference such as Dragon& dragon
instead of value such as Dragon dragon
. This prevents unnecessary copies.