我是C ++的新手,我在理解如何同时处理多个命名空间时遇到了困难。在我的MVC应用程序中,视图需要引用控制器来转发动作,而控制器需要引用视图来显示某些动作。
我已经从我的应用程序中删除了几乎所有内容,并且我仍然有很多关于nomespace和未声明标识符的编译错误。这是剥离的代码:
#ifndef _geometria
#define _geometria
namespace core_stuff {
/*this namespace contains Model and Controller */
class Model {
public:
Model();
//void doSomething();
};
class Controller {
public:
Controller();
void setView(ui_stuff::View v);
};
}
namespace ui_stuff {
/*this namespace contains View and other UI classes libraries, not included here because I am semplifying the whole stuff */
class View {
public:
View();
void setController(core::Controller c);
};
}
#endif
这是实施:
#include "geometria.h"
#include <iostream>
//implementation of core_stuff namespace
core_stuff::Model::Model() { }
core_stuff::Controller::Controller() { }
void core_stuff::Controller::setView(ui_stuff::View v) {
//do some kind of operation in my view
}
//implementation of ui_stuff namespace*/
ui_stuff::View::View() { /* */ }
void ui_stuff::View::setController(core_stuff::Controller c) {
//do some kind of operation on the controller
}
/* main */
int main (int nArgs, char* args[]) {
core_stuff::Model m;
core_stuff::Controller c;
ui_stuff::View v;
v.setController(c);
c.setView(v);
}
很长的编译错误列表中的第一个涉及
void setView(ui_stuff::View v);
在头文件中,无法访问ui_stuff命名空间:
第(20)行:错误C2653:'ui_stuff'不是类或命名空间的名称
我该如何解决这个问题?
答案 0 :(得分:3)
在使用之前,您需要ui_stuff::View
的前瞻性声明
namespace ui_stuff
{
class View; // a forward declaration of ui_stuff::View
}
namespace core_stuff
{
class Controller {
void setView(ui_stuff::View& v);
};
}
namespace ui_stuff
{
class View
{
public:
void setController(core_stuff::Controller& c);
};
}
我也把它作为参考传递给了我。这可能是你想要的(不是视图的副本)。
简要说明我更改声明的原因:您无法将View
值传递给Controller
的方法,传递{{1通过值Controller
。这是因为,当您传递值时,必须定义您传递的整个对象。您无法在视图之前完全定义控制器,因为控制器依赖于视图的完整定义。但是你不能出于同样的原因在控制器之前定义视图,因此&#34;通过引用传递&#34;位。
声明两个类后,您可以定义它们彼此交互的方式。
答案 1 :(得分:1)
作为dutt saide,C ++按顺序解析。这意味着在C ++代码的每一行中,编译器只知道到目前为止定义的内容。
要解决您的问题,您应该在核心内容之前移动ui_stuff,但您还应该查看类存根。例如:
namespace ui_stuff {
class View; //This class exists but I will not define it yet.
}
问题是您可以不将View作为副本传递,因为您不确切知道什么是View。但是,您可以作为指针或引用传递(因为两个指针都不需要知道数据的大小)。
因此,在您的代码中,而不是这样做:
class Controller {
public:
Controller();
void setView(ui_stuff::View v);
};
你会这样做:
class Controller {
public:
Controller();
void setView(ui_stuff::View& v);
};
&
表示您希望引用已存在的视图,而不是新副本。