我需要在类C 中定义所有私人功能和变量

Do I need to define all private functions and variables in class header C++

本文关键字:功能 变量 定义      更新时间:2023-10-16

在C 类中,我是否应该将我的私人功能和变量放在类标题定义的私有部分或类源文件中,为什么?

例如:

// Header
class MyClass {
public:
    void doSomething();
private:
    int a = 0;
}
// Source
void MyClass::doSomething()
{
    // Do something with `a`
}

// Header
class MyClass {
public:
    void doSomething();
}
// Source
int a = 0;
void MyClass::doSomething()
{
    // Do something with `a`
}

我一直认为,在编程时,最好使函数/变量的范围尽可能小。因此,不应该将var a的范围限制为源文件范围吗?

它们不是等效的。第一个示例

// Header
class MyClass {
public:
    void doSomething();
private:
    int a = 0;
}
// Source
void MyClass::doSomething()
{
    ++a;
    cout << a << endl;
}
int main()
{
    MyClass x, y;
    x.doSomething();
    y.doSomething()
}

输出

1
1

第二个示例

// Header
class MyClass {
public:
    void doSomething();
}
int a = 0;
// Source
void MyClass::doSomething()
{
    ++a;
    cout << a << endl;
}
int main()
{
    MyClass x, y;
    x.doSomething();
    y.doSomething()
}

输出

1
2

在第一个示例中,a是类变量,因此xy具有自己的a副本。在第二个示例中,只有一个全局变量a,因此输出不同。

您可以使用pimpl成语...或者,您可以使用PIMPL成语的此变体,其中实现的内存由接口类直接提供:

在文件MyClass.hpp中:

class MyClass{
  private:
    std::byte buffer[N];
  public:
    MyClass();
    void public_method();
    ~MyClass();
  };

在类MyClass.cpp中:

#include "MyClass.hpp"
namespace{
  struct MyClassImpl{
     private:
       int val=0;
     public:
       void secret_method(){/*...*/}
     };
  inline const MyClassImpl& 
  get(const std::byte* buffer){
    //In theory, in C++17 you should use std::launder here to be standard compliant
    //in practice, compilers generate the expected code without std::launder
    //and with std::launder they generate horrible and inefficient code!
    return *reinterpret_cast<const MyClassImpl*>(buffer);
    }
  inline MyClassImpl& 
  get(const std::byte* buffer){
    //idem here to be c++17 standard compliant launder is necessary
    //in practice, it would be a mistake.
    return *reinterpret_cast<MyClassImpl*>(buffer);
    }
 }
 MyClass::MyClass(){
   new(buffer) MyClassImpl{};
   }
 MyClass::~MyClass(){
   get(buffer).~MyClassImpl();
   }
 void
 MyClass::public_method(){
    /*....*/
    get(buffer).secret_method();
    /*....*/
    }

与经典的pimpl成语相比:

  • pros :更少的内存访问,没有内存分配,更有效

  • cons> cons :易犯错,界面中实现"泄漏"的大小。