面向对象编程问题:全局对象

时间:2009-08-04 18:56:31

标签: c++ oop

我可能有一个非常简单的问题,但我还没有找到合适的设计决定。 基本上,我有4个不同的类,每个类都有10个以上的方法。

这些类中的每一个都应该使用相同的TCP Socket;此对象在程序执行期间保持套接字对服务器开放。我的想法是将TCP obejct声明为“global”,以便所有其他类都可以使用它:

classTCP TCPSocket;

class classA  
{  
    private:   
    public:   
    classA();  
    ...   
};    

class classB  
{  
    private:   
    public:   
    classB();  
    ...   
};    

不幸的是,当我这样声明时,我的C ++编译器给出了一条错误消息,即某些初始化数据写在可执行文件中(???)。所以我想知道是否有任何其他方式我可以声明这个TCP对象,以便它可用于所有其他类及其方法?

非常感谢!

7 个答案:

答案 0 :(得分:9)

我建议您将实例保留在初始化代码中,并将其传递到需要它的每个类中。这样,用模拟实现代替测试就容易得多。

答案 1 :(得分:4)

这听起来像是Singleton设计模式的工作。

答案 2 :(得分:4)

在正确的时间使用依赖注入时,我的声音更多,因为我倾向于尽可能地避免使用Singleton(Singleton只是访问GLOBLAS的另一种方式,并且需要避免它)

已经在SO上讨论了Singleton vs Dependency Injection,检查了“依赖注入”标签(抱歉没有发布一些链接,但是不允许我发布多个链接作为新用户)

Wikipedia: Dependency Injection

根据您当前的代码示例,应该修改为允许在每个类的构造函数上注入Socket:

class classA  
{  
    private:   
    public:   
    classA(TCPSocket socket);  
    ...   
};    

class classB  
{  
    private:   
    public:   
    classB(TCPSocket socket);  
    ...   
};

答案 3 :(得分:1)

将套接字传递给每个对象的构造函数。然后创建一个单独的factory class,创建它们并传入适当的套接字。所有代码都使用具有相同套接字所需的对象集,然后通过此工厂对象的实例创建它们。这解耦了应该使用单个套接字的类,同时仍允许执行共享套接字规则。

答案 4 :(得分:0)

最好的方法是使用Singleton。这是它在Java中的实现

Singleton类:

public class SingletonTCPSocket {
  private SingletonTCPSocket() {
    // Private Constructor
  }

  private static class SingletonTCPSocketHolder { 
    private static final SingletonTCPSocket INSTANCE = new SingletonTCPSocket ();
  }

  public static SingletonTCPSocket getInstance() {
    return SingletonTCPSocket.INSTANCE;
  }

  // Your Socket Specific Code Here
  private TCPSocket mySocket;
  public void OpenSocket();
}

需要套接字的类:

public class ClassA {
  public ClassA {
    SingletonTCPSocket.getInstance().OpenSocket();  
  }  
}

答案 5 :(得分:0)

当你的程序中有一个独特的对象并在很多地方使用时,你有几个选择:

  • 传递对所有对象的引用

  • 使用或多或少隐藏的全局(单例,单态,......)

每种方法都有其缺点。他们评论很好,有些人对这些问题有很强烈的意见(搜索“单身反模式”)。我会给出一些,而不是试图完成。

  • 传递引用是繁琐而且混乱的代码;所以你最终将这些引用保留在一些长寿命的对象中,以减少参数的数量。当“独特”对象不再具有独特性的时候,你准备好了吗?否:您有多条通往唯一对象的路径,您会看到它们现在引用不同的对象,并且它们使用不一致。调试这可能是一个噩梦,比从全局方法修改代码到传递方法更糟糕,而且由于代码已经准备好而没有在计划中进行计划。

  • 全球性的接近问题更为人所知。它们引入了隐藏的依赖关系(因此重用组件更加困难),意外的副作用(获得正确的行为更加困难,修复某个地方的错误会触发其他组件中的错误),测试更加复杂,......

在你的情况下,拥有一个插座不是本质上独特的东西。必须在程序中使用另一个或在某个地方重用组件的可能性是套接字不再具有独特性似乎相当高。我不是采用全局方法,而是采用参数化方法。请注意,如果您的套接字本质上是唯一的 - 表示它是通过网络日志记录 - 您最好将其封装在为此目的设计的对象中。例如记录。然后使用类似全局的功能是有意义的。

答案 6 :(得分:0)

正如大家所提到的,全局变形很糟糕等等。

但是为了实际解决你所拥有的编译错误,我很确定这是因为你在头文件中定义了全局,它被包含在多个文件中。你想要的是这个:

something.h

extern classTCP TCPSocket; //global is DECLARED here

class classA  
{  
    private:   
    public:   
    classA();  
    ...   
};

something.cpp

classTCP TCPSocket; //global is DEFINED here