我是否需要在类头C ++中定义所有私有函数和变量

时间:2018-02-08 08:25:29

标签: c++

在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的范围限制在源文件的范围内吗?

2 个答案:

答案 0 :(得分:2)

它们并不等同。第一个例子

// 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,因此输出不同。

答案 1 :(得分:0)

你可以使用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成语相比:

  • 优点:内存访问量减少,堆上没有内存分配,效率更高

  • 缺点:容易出错,执行的大小&#34;泄漏&#34;在界面中。