【问题标题】:How to add a property to a class [closed]如何将属性添加到类[关闭]
【发布时间】:2018-03-14 14:14:35
【问题描述】:

我正在开发一个基于模板、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;

我自己刚刚添加了最后一个条目 getDebuggerTimergetFileTimer,但由于编译器错误 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 发明),它们将使您的代码工作。

?????

有人能解释一下吗?

【问题讨论】:

  • C# 背景?我问是因为 C++ 没有定义任何称为“属性”的东西。这可能有助于澄清您要做什么。
  • 我很确定这与模板或 STL 无关。
  • 这里的 STL 完全是无辜的,我不知道你在抱怨什么。
  • 你的老板应该可以简单地回答这个问题。除非他给你不问的理由,否则我会说下次问你老板而不是问我们:-)
  • 您实际上缺少大量 C++ 知识,其中包括“如何声明类型”。这整个问题只是将手指指向与缺少的#include 或声明无关的随机特征。因此,VTC“不太可能帮助未来的读者”。在您的辩护中,MSVC 在这种情况下的错误消息非常无用。

标签: c++ stl


【解决方案1】:

如果要将Timer 聚合到类定义中,编译器需要知道Timer 是什么。所以,你可以使用#include "Timer.h"(使用正确的标题)。

你的老板做了两件事

  1. 使用指针而不是成员对象。从而允许它工作 使用前向声明而不是包含。
  2. 使用智能 指针而不是原始指针。这是一种很好的做法。

【讨论】:

  • #include "Timer.h" 是不允许的,因为循环引用(尽管我们没有找到循环引用的位置:我尝试升级我的视觉工作室,以便以图形方式显示包含物,但这导致我的整个 Visual Studio 环境不再工作)。
  • 这完全是另一个问题。在我见过的任何大型项目中,都有一个生成包含树的工具。当引入(或尝试)循环时,您查找树并在适当的地方使用线索蝙蝠。在这种情况下,它闻起来像 Timer.h 包含太多东西。因为聚合一个 Timer 听起来很合理。
  • 但是使用共享指针不太可能是最佳选择。
【解决方案2】:

这与模板和STL无关。

你应该看看前向声明是什么:

你的老板做了什么

class Timer;

是对编译器说“嘿,看,有一个你还不知道的叫做 Timer 的东西,相信我并为它保留一些空间”。

编译器回答没问题,但它必须知道为构造该对象分配多少空间。由于您使用一个对象并且不包含包含它的头文件,因此编译器不知道它需要多少空间并给您一个错误。如果您改用指针(或智能指针),编译器确实只需要为指针保留空间,它就可以做到。当然,如果你想在实现中使用它,你必须包含时间标题。

出于同样的原因,您不能转发声明您将要继承的类。

timer.h

class Timer
{
public:
   void time() { std::cout << "time!"; }
}

你的班级.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 有很好的解释。

【讨论】:

  • 我不理解反对票
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-29
  • 2018-01-05
相关资源
最近更新 更多