我正在开发一个新的应用程序,基于模板,STL,名称空间,......(我的同事已经采取了所有必要的步骤来制作一个混乱),现在我只想为一个类添加一个属性,并且这不起作用,让我告诉你):
在标题文件中:
namespace utils{
class Logging_Manager : public Singleton<Logging_Manager> {
friend Singleton<Logging_Manager>;
Logging_Manager();
private:
std::vector<std::shared_ptr<Single_Logger>> logging_modules;
LogLevelType loglevel; // 0 : no logging, 1 : info logging, (2-4 are not used), 5 : debug, 6 : everything
public:
Timer getDebuggerTimer;
Timer getFileTimer;
我刚刚添加了最后一个条目getDebuggerTimer
和getFileTimer
,由于编译器错误C3646和C4430,因此无法编译。
我的意思是两者都是Timer
类型的属性,我不是指那些可能是抽象的,虚拟的或任何方法的模板,不是它们只是意味着属性,仅此而已。
由于我没有找到将两个计时器添加到我的头文件的方法,我的老板刚刚解决了这个问题如下:
class Timer; // this class is defined elsewhere, how can it be put here and make things work?
namespace utils{
class Logging_Manager : public Singleton<Logging_Manager> {
friend Singleton<Logging_Manager>;
Logging_Manager();
private:
std::shared_ptr<Timer> getDebuggerTimer;
std::shared_ptr<Timer> getFileTimer;
换句话说:他没有添加包含,但他添加了对标题不知道的内容的引用:class Timer
。
最重要的是,他添加了一个共享指针,它神奇地做了一些事情。
我完全迷失在这里:看起来STL已经添加了以下编程规则:
- 如果你想要一些工作,不要添加包含,但添加一个引用(但你的代码如何知道引用的含义?)
- 您可以添加共享指针(或其他STL发明),谁将使您的代码工作。
···
有人可以解释一下吗?
答案 0 :(得分:2)
如果要将Timer
聚合到类定义中,编译器需要知道Timer
是什么。因此,您可以使用#include "Timer.h"
(使用正确的标题)。
你的老板所做的是双重的
答案 1 :(得分:0)
这与模板和STL无关。
您应该查看前向声明是什么:
你的老板用那个做了什么
class Timer;
是对编译器说“嘿看,还有一些叫做Timer的东西,你还不知道,相信我并预留一些空间”。
编译器回答确定,但它必须知道分配多少空间来构建该对象。由于您使用了一个对象并且不包含包含它的头文件,因此编译器不会知道它占用太多空间并且会给您一个错误。如果您使用指针(或智能指针),编译器确实只需要为指针保留空间,它就可以执行此操作。然后,如果你想在实现中使用它,你必须包括时间标题。
出于同样的原因,你无法转发声明你要继承的类。
timer.h
class Timer
{
public:
void time() { std::cout << "time!"; }
}
yourclass.h
class Timer; // forward declaration
class Manager
{
public:
void doStuff() {}
private:
Timer* t1; // this will work
std::shared_pointer<Timer> t2; // this will work
//Timer t3; // this one don't
}
}
此案例不起作用:
class Timer;
class SpecialTimer : public Timer
{
// ... do stuff
}
关于前瞻性声明的一些链接:
https://en.wikipedia.org/wiki/Forward_declaration
This Post有一个很好的解释。