C++类方法如何操作其他类实例,出现unknown type name报错如何解决
报错原因
C++采用从上到下的单遍编译逻辑,你在Knight类中定义Attack方法时,使用了Dragon作为参数类型,但此时Dragon类还没有完成定义,编译器无法识别该类型,就会抛出unknown type name 'Dragon'错误。
解决步骤
添加类的前置声明
在ISubject类定义完成后、Knight类定义前,添加一行class Dragon;,提前告诉编译器Dragon是一个存在的类,暂时不需要知道它的完整结构。调整
Attack方法的参数类型
前置声明的类属于不完全类型,不能直接作为值参数使用(编译器无法计算它的内存占用大小),所以把参数修改为引用或者指针类型即可,示例:
// 修改为const引用类型,也可以用Dragon* dragon指针类型 void Attack(const Dragon& dragon) { this->message_ = "I am attacking"; Notify(); std::cout << "todo\n"; }
如果你一定要使用值传递参数,需要把Attack方法的实现挪到Dragon类定义完成之后的位置。
- 修复其他语法问题
- C++中使用
new创建对象时需要加构造括号,new Knight要改为new Knight(),new Dragon改为new Dragon() - 你在
ClientCode中调用knight->Attack()时没有传入Dragon类型的参数,需要先创建Dragon实例再传入方法 - C++没有自动垃圾回收,
new出来的对象使用完成后需要手动delete释放,避免内存泄漏
修正后的核心代码示例
#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; }; // 新增Dragon类前置声明 class Dragon; class Knight : public ISubject { public: void Attach(IObserver *observer) override { list_observer_.push_back(observer); } void Notify() override { auto iterator = list_observer_.begin(); while (iterator != list_observer_.end()) { (*iterator)->Update(message_); ++iterator; } } void CreateMessage(std::string message = "Empty") { this->message_ = message; Notify(); } // 修改参数为const引用 void Attack(const Dragon& dragon) { this->message_ = "I am attacking"; Notify(); std::cout << "todo\n"; } private: std::list<IObserver *> list_observer_; std::string message_; }; // 原有Dragon类定义保持不变即可 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_; }; // GameManager类保持不变 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); // 新增Dragon实例创建 Dragon *dragon1 = new Dragon(); knight->CreateMessage("I exist"); knight->CreateMessage("Going to attack dragon1"); // 传入dragon参数 knight->Attack(*dragon1); // 手动释放内存 delete dragon1; delete gameManager; delete knight; } int main() { ClientCode(); return 0; }
内容的提问来源于stack exchange,提问作者NinStarRune
相关产品推荐
相关产品推荐

