【问题标题】:Shared variable among classes c++c++ 类之间的共享变量
【发布时间】:2012-11-08 22:51:09
【问题描述】:

我有多个类需要共享另一个类的单个实例。公开地,应该不知道这个类的存在。执行以下操作是否合适? (书面测试)

#include <iostream>

class hideme
{
    private:
        int a;

    public:
        void set(int b) { a = b; }
        void add(int b) { a += b; }
        int get() { return a; }

        hideme() : a(0) { }
};


class HiddenWrapper
{
    protected:
        static hideme A;

};

hideme HiddenWrapper::A;

class addOne : public HiddenWrapper
{
    public:
        void add() { A.add(1); }
        int get() { return A.get(); }
};

class addTwo : public HiddenWrapper
{
    public:
        void add() { A.add(2); }
        int get() { return A.get(); }
};


int main()
{
    addOne a;
    addTwo b;

    std::cout << "Initialized: " << a.get() << std::endl;

    a.add();
    std::cout << "Added one: " << a.get() << std::endl;

    b.add();
    std::cout << "Added two: " << b.get() << std::endl;

    return 0;
}

对于它的价值,hideme 是我正在尝试围绕其设计外观的库的一部分,并且其他类具有与静态 hideme 交互的库中的成员。

另外,如果为HiddenWrapper 编写的头文件没有对应的源文件,那是定义其静态成员的最佳位置吗?带有一个包含保护。

还有其他方法可以解决这个问题吗?据我所知(不是很远),我只能通过友谊来解决它,我对此很警惕。

【问题讨论】:

  • 当使用它的最后一个对象被销毁时,该单个对象是否应该被销毁?一个有私人成员和朋友的单身人士就够了吗?
  • 我的规则始终是公共继承适用于 IS A 关系。当一个类需要成为另一个类的更具体的实例时,您可以使用它。您可以使用私有继承,这样会更好一些。另一种选择是让每个人都持有引用或共享指针。
  • 为了避开朋友,我在多个地方阅读过,所以我一直这样做。不过这是一种可能。我现在正在研究组合,看起来它涉及共享引用或指针。谢谢
  • friend 关键字不会破坏封装,它可以帮助您改进它。

标签: c++ inheritance static-members


【解决方案1】:

您可以通过不在使用它的翻译单元之外访问某个类来阻止对它的访问。

// public_header.h

class A {
    void bar();
};
class B {
    void foo();
}

// private_implementation.cpp
#include "public_header.h"

namespace {
  class hidden { void baz() {} };

  hidden h;
}

void A::bar() {
    h.baz();
}
void B::foo() {
    h.baz();
}

这个类只能被 A::bar 和 B::foo 使用。 hidden 类型和变量 h 在技术上仍然具有外部链接,但没有其他翻译单元可以说出它们的名字。

【讨论】:

  • 有趣的方法,像 BeachWalker 和 Billz 提到的那样,什么情况下可能更喜欢在构造函数中注入对隐藏对象的引用?
  • @user1758039 这确实使用了通常应该避免的全局变量。但是通过构造函数传递共享对象需要类型在外部可见。这取决于你为什么要隐藏东西。当然继承也意味着类是公开可见的......
【解决方案2】:

有时通过构造函数(也称为组合而不是继承)注入共享资源(通过引用或指针)是一个更好的主意。这种方式使您能够共享或不共享(例如,拥有不是代码的线程安全变体)。更多信息请参见http://de.wikipedia.org/wiki/Inversion_of_Control原理。

【讨论】:

  • 谢谢,现在正在调查!
【解决方案3】:

这实现了一个围绕其他类的单例并将其隐藏 用户:

class hideme {};

// fwd declarations
class x;

// library internal
class S
{
  S() = delete;
  S(S const&) = delete;
  void operator=(S const&) = delete;
private:
  static hideme& getInstance()
  {
    static hideme instance;
    return instance;
  }

  friend x;
};

// library classes
class x {
  hideme& s;
public:
  x() : s(S::getInstance()) {}
};

int main()
{
  x x;
  return 0;
}

这不处理您实际需要hideme 的情况 当没有其他对象不再使用它时,实例将被销毁。为了 你需要使用参考来获得更多的创造性 计数。

我也应该说我认为这是一个坏主意。单身人士几乎 永远都是。

【讨论】:

  • 为什么单身人士通常是个坏主意?我目前不打算将其用作一个,但学习总是很好的。
  • @user1758039 单例就像全局变量,但在某些方面更糟。很少有你真的想要一个不可能多次实例化的类型,而不是你碰巧想要一个的类型。如果你只想要一个实例,那就做一个,不要把这个限制加入到类中。
【解决方案4】:

一般来说,最好的方法是,如果您在主要部分有一个变量,并希望与所有类共享它。
例如,如果类 X 对此 var 进行了更改,则更改也发生在 main 中的 var 上:您可以使用 EXTEND
************************主要*********************

#include <iostream>
using namespace std;

#include "Game.hpp"
//0: not specified yet; 1:singlemode; 2:multiplayerMode
int playingMode = 0;

int main()
{
    Game game;
    game.Run();
    std::cout<< playingMode << std::endl; 
    return 0;
}  

*********************** X 级 *****************

#include <iostream>
using namespace std;

extern int playingMode;

....
....

if(m_isSinglePressed)
    {
        playingMode = 1;
        ...

    }
    else if(m_isMultiPressed)
    {
        playingMode = 2;
        ...
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-08
    • 2012-10-27
    • 2013-07-26
    • 2018-04-25
    • 2011-09-14
    • 2013-12-28
    • 1970-01-01
    相关资源
    最近更新 更多