C++ 私有静态成员与在cpp文件中包含它们之间的差异

C++ 私有静态成员与在cpp文件中包含它们之间的差异,c++,C++,假设我希望类A有一个变量和一个函数,该变量和函数可用于所有实例,但仅限于它们。 我有两种方法(或者还有其他方法吗?) 将它们作为私有静态成员: class A { ... private: static int myInt; static void myMethod(); ... }; 只需将它们保存在cpp文件中: // h file class A { ... }; // cpp file static int myIn

假设我希望类A有一个变量和一个函数,该变量和函数可用于所有实例,但仅限于它们。
我有两种方法(或者还有其他方法吗?)

将它们作为私有静态成员:

class A {
    ...

    private:
        static int myInt;
        static void myMethod();

    ...
};
只需将它们保存在cpp文件中:

// h file
class A {
    ...
};

// cpp file
static int myInt;
static void myFunction() { ... }
在我看来,这两个选项都很好,但除了与设计相关的参数外,还有什么区别?
有哪个选项比另一个更好吗?
是否存在任何性能或优化问题?
谢谢


编辑 似乎我不够清楚,所以这里有一个更好的例子(保留旧的例子,以便前面的评论/答案有意义):

第一种选择:

// h file
class A {
    public:
        A();
        ~A();

        void doSomething();

    private:
        static std::queue queue;
        static boost::mutex mutex;

        static void initQueue();
};

// cpp file

// let's assume this method can be called multiple times but only initiates the queue on the first call
void A::initQueue() {
    boost::unique_lock<boost::mutex> lock(A::mutex);
    ...
}

void A::A() {
    A::initQueue();
}

void A::doSomething() {
    // have full access to the A::queue/A::mutex
}
//h文件
甲级{
公众:
A();
~A();
无效剂量();
私人:
静态std::队列;
静态增强:互斥互斥;
静态void initQueue();
};
//cpp文件
//假设此方法可以被多次调用,但只在第一次调用时启动队列
void A::initQueue(){
boost::unique_lock锁(A::mutex);
...
}
void A::A(){
A::initQueue();
}
void A::doSomething(){
//具有对A::队列/A::互斥体的完全访问权限
}
第二种选择:

// h file
class A {
    public:
        A();
        ~A();

        void doSomething();
};

// cpp file
static std::queue queue;
static boost::mutex mutex;

static void initQueue() {
    boost::unique_lock<boost::mutex> lock(Amutex);
    ...
}


void A::A() {
    initQueue();
}

void A::doSomething() {
    // have full access to the queue/mutex
}
//h文件
甲级{
公众:
A();
~A();
无效剂量();
};
//cpp文件
静态std::队列;
静态增强:互斥互斥;
静态void initQueue(){
boost::独特的_锁(Amutex);
...
}
void A::A(){
initQueue();
}
void A::doSomething(){
//具有对队列/互斥体的完全访问权限
}
至于可见性,我的意思是,通过包含A.h,我无法访问变量/函数,只能从A类中访问。

我不是说如何防止它们受到恶意代码或其他东西的攻击。

区别在于私有静态成员是类的一部分,因此可以访问类实例的私有和受保护成员。自由函数不会

例如:

class A {
  A(a) : _a(a) {}
private:
  // legal - _a is accessible because get_a is part of A
  static int get_a(const A& a) { return a._a; } 
private:
  int _a;
};

// illegal - _a is a private member of A
static get_a(const A& a) {
  return a._a;
}
编辑以响应OP的编辑


两种实现都有效。

私有成员是类用户无法访问的实现细节。在头文件中公开它们会创建不必要的编译依赖项。例如,私有成员可能需要包括其他头文件,这会减慢包括头文件的翻译单元的编译;更改头文件中的实现细节需要重新编译其所有用户。因此,最好只在头文件中公开用户可以直接使用的内容(公共API),并尽可能避免在公共API头中公开实现细节

赫伯·萨特(Herb Sutter)对这个问题进行了彻底的治疗


您可以轻松地将所有非公共静态类成员移动到.cc文件和未命名的命名空间中

非静态数据成员可以移动到Pimpl中,也可以隐藏在抽象接口后面。Pimpl的优势在于,它不需要用户直接处理智能指针和工厂,也不使用虚拟调用,虚拟调用的速度可能比非虚拟调用稍慢


隐藏数据成员实现的运行时成本是,成员函数的实现必须在
.cc
中,这样在不生成链接时代码的情况下,类API的调用就不能内联。

@Smac89我用更好的示例和解释编辑了我的问题。我的意思是,如果我包含A.h,我将无法访问互斥对象和队列对象,也无法访问init函数。在第二个选项中,通常更倾向于将
queue
mutex
放入匿名命名空间,而不是将它们设置为静态。@StephenNutt谢谢,没有意识到这一点,现在正在阅读谢谢,这绝对正确,但不是我的目标。显然,如果我需要从私有函数访问其他类成员,那么我会将其作为一个方法来实现。我知道它们是有效的,我同时使用了这两种方法,问题是是否有区别@MaximYegorushkin指出编译时间有差异例如,在函数符号对链接器和调试器的可访问性方面有一些差异,但仅此而已。好的,所以他建议了第三个选项,为实现提供私有类/结构成员,然而,我认为这将是混乱的工作。根据你的回答,如果我理解正确的话,你说第二个选项更适合编译?如果是,运行时间如何?谢谢。@NitzanTomer为您更新了答案。